Cheat Sheet para programadores full stack

WORK IN PROGRESS ;)

Artigo criado por necessidades práticas no desenvolvimento de aplicativos para dispositivos móveis. Porém, com o tempo, fui adicionando mais linguagens para comparação, migração de código ou interesse histórico. Fui parcialmente inspirado no artigo icônico de Dare Obasanjo comparando C# e Java.

É quase como um Rust vs Go vs C++ vs Swift vs Kotlin vs Java vs C# vs JavaScript vs TypeScript vs Dart vs Python :P Mas também estou começando a comparar duas linguagens funcionais (Lisp e Haskell). Linguagens de mais baixo nível como Web Assembly text format, LLVM e Assembly. Linguagens interpretadas como Ruby e PHP (populares em hospedagens compartilhadas) e VB6 e Smalltalk nessa categoria também. Finalmente, linguagens que de algum modo foram ou ainda são populares como ActionScript, Ada, Objective-C e Object Pascal (Delphi).

Não viu a linguagem que você queria aqui ou gostaria de contribuir com alguma nova linguagem? Esta página é um esforço individual, mas você pode tentar o site colaborativo http://www.rosettacode.org.

Índice

Olá Mundo

Rust - Olá Mundo - main.rs

// requer uma função main fn main() { println!("Olá Mundo"); }

Go - Olá Mundo - main.go

// requer um pacote package main // requer uma biblioteca para IO import ("fmt") // requer uma função main func main() { fmt.Println("Olá Mundo") }

C++ - Olá Mundo - main.cpp

// requer uma biblioteca para IO #include <iostream> // requer uma função main na raiz int main(int argc, const char* argv[]) { std::cout << "Olá Mundo"; // requer um código de retorno return 0; }

Objective-C - Olá Mundo - main.m

// requer uma biblioteca para IO #import <Foundation/Foundation.h> // requer uma função main int main(int argc, const char* argv[]) { NSLog(@"Olá Mundo"); // requer um código de retorno return 0; }

Swift - Olá Mundo - main.swift

print("Olá Mundo")

Kotlin - Olá Mundo - main.kt

// requer uma função main fun main(args: Array<String>) { println("Hello, world!") }

Java - Olá Mundo - OlaMundo.java

public class OlaMundo { // requer um método estático main em uma classe public static void main(String[] args) { System.out.println("Olá Mundo"); } }

C# - Olá Mundo - OlaMundo.cs

// C# 9+ System.Console.WriteLine("Olá Mundo"); // C# 8- public class OlaMundo { // requer um método estático main em uma classe public static void Main(string[] args) { System.Console.WriteLine("Olá Mundo"); } }

Dart - Olá Mundo - main.dart

// requer uma função main void main() { print('Olá Mundo'); }

TypeScript - Olá Mundo - main.ts

console.log('Olá Mundo')

JavaScript - Olá Mundo - main.js

console.log('Olá Mundo')

ActionScript - Olá Mundo - main.as

trace('Olá Mundo')

Python - Olá Mundo - main.py

print('Olá Mundo')

PHP - Olá Mundo - index.php

<?= 'Olá Mundo' ?> ou <?php echo 'Olá Mundo' ?> ou <?php echo <<<'EOD' Olá Mundo EOD; ?> embora o primeiro código que você vai escrever provavelmente seja <?php phpinfo(); ?>

VBA / VB6 - Olá Mundo - main.bas

Debug.Print "Olá Mundo"

Ada - Olá Mundo - main.adb

-- requer uma biblioteca para IO with Ada.Text_IO; use Ada.Text_IO; -- requer uma função main -- mas pode ter um nome diferente procedure Main is begin Put_Line("Olá Mundo"); end Main;

Object Pascal (Delphi) - Olá Mundo - main.dpr

// requer uma função main // mas pode ter um nome diferente program Main; begin WriteLn('Olá Mundo'); end.

Ruby - Olá Mundo - main.rb

puts "Olá Mundo"

SmallTalk - Olá Mundo - main.st

Transcript show: 'Olá Mundo'.

Common Lisp - Olá Mundo - main.lisp

(print "Olá Mundo") ; ou para retornar uma string do programa "Olá Mundo"

Haskell - Olá Mundo - main.hs

putStrLn "Olá Mundo" -- ou para retornar uma string do programa "Olá Mundo"

F#

printfn "Olá Mundo"

Web Assembly text format - main.wasm

(module ;; web assembly does not interact with the DOM ;; so we must import certain browser functions (import "console" "log" (func $log (param i32 i32))) (import "js" "mem" (memory 1)) (data (i32.const 0) "Hello World" ) (func (export "main") i32.const 0 ;; pass offset 0 to log i32.const 11 ;; pass length 11 to log call $log ) )

JavaScript

let memory = new WebAssembly.Memory({ initial: 1 }); // object to be imported by web assembly let importObject = { console: { // web assembly can only send numbers and bytes // so it requires a special console.log log: function(offset, length) { var bytes = new Uint8Array(memory.buffer, offset, length); var string = new TextDecoder('utf8').decode(bytes); console.log(string); } }, js: { mem: memory } }; WebAssembly .instantiateStreaming( fetch('main.wasm'), importObject ) .then(obj => { obj.instance.exports.main(); });

LLVM IR

source_filename = "main" ; requer uma função externa para IO declare i32 @puts(i8* nocapture) nounwind @helloWorld = private constant [10 x i8] c"Olá Mundo\00" ; requer um bloco main define void @main() { entry: %cast210 = getelementptr [10 x i8], [10 x i8]* @helloWorld, i64 0, i64 0 call i32 @puts(i8* %cast210) ; requer um código de retorno TODO testar ret i32 0 }

Assembly

section .text global _start ; requer um bloco "main" _start: call io call exit io: ; requer um system call para IO mov eax, system_interrupt_write mov ebx, standard_output mov ecx, message mov edx, message_length int system_call_interrupt ret exit: ; requer um código de retorno mov eax, system_interrupt_exit int system_call_interrupt ret section .data ; dados do programa message db 'Olá Mundo', 0xa message_length equ $ - message ; dados padrões do sistema standard_output equ 1 system_interrupt_write equ 4 system_interrupt_exit equ 1 system_call_interrupt equ 0x80
  1. Python / Swift / VB6
  2. JavaScript / PHP
  3. Rust
  4. Dart / Kotlin / Object Pascal (Delphi)
  5. C# / Java
  6. Go
  7. Ada
  8. C++ / Objective-C
  9. LLVM IR
  10. Assembly
  11. Web Assembly text format

Python e Swift são as mais simples de todas. Nem ; elas precisam, e seu uso nem é recomendado no caso do Swift.
Curioso encontrar VB6 aqui na mesma posição.
JavaScript perde por pouco. Também não requer ; embora ao contrário do que ocorre com Swift, seu uso seja recomendado. Seu console.log também é um pouco maior que o método print.
C# 9+ vem logo atrás, pois tem mais um namespace a ser digitado antes da função.
PHP foi criado para ser utilizado em conjunto com HTML, e por isso requer tags para abrir e fechar os blocos de código. Possui uma tag de atalho para casos simples e uma alternativa para textos longos, que acho confusa e pessoalmente nunca vi ser usada. Usos mais complexos tendem a utilizar frameworks ou mecanismos de template
Rust ainda requer uma função main, mas o retorno dela não precisa ser declarado explicitamente. Diferente das demais linguagens, usa um macro para IO, por isso print! leva uma exclamação (não, não era porque eu estava entusiasmado quando escrevi o código).
Dart, Kotlin e Object Pascal (Delphi) tem uma ou outra coisa a mais qua deve ser digitada a mais do qua Rust. Object Pascal (Delphi), assim como Ada e VB6 utilizam mais palavras reservadas do que símbolos.
C# 8- e Java são idênticos, ambos requerendo uma classe que contenha o método main. Sentiu uma leve pressão para escrever orientado a objeto aqui? Também é recomendado que o nome do arquivo tenha o mesmo nome da classe.
Go é quase tão comprido quanto C++ e Objective-C. Não requer que a função main retorne um inteiro, mas requer um pacote.
Ada
C++ e Objective-C são bastante parecidos pois possuem forte influência do C.
LLVM IR TODO
Assembly é completamente diferente dos demais. Se bem organizado para este exemplo simples, até fica bastante legível, embora verboso. A ordem invertida dos argumentos e nome da função é pouco intuitiva.
Web Assembly text format

Tipo da linguagem

Rust

Nativa compilada
Usa LLVM

Go

Nativa compilada

C++

Nativa compilada

Objective-C

Nativa compilada

Swift

Nativa compilada
Usa LLVM

Kotlin

Process virtual machine
Register based vm
* Kotlin native é nativo

Java

Process virtual machine (JVM)
Stack based vm
No Android utiliza Ahead of time compilation (AOT),
Em versões mais antigas utilizava register based vm (Dalvik)

C#

Process virtual machine (CLR)
Stack based vm
* .NET native é nativo

Dart


Stack based vm (Dart VM)
com Ahead of time (AOT) ou Just in Time (JIT) compilation

TypeScript

É transcompilada para JavaScript
Não é executada diretamente

JavaScript

Interpretada + Just in time compiler
Runtime dentro dos navegadores ou Node.js
Spidermonkey para Firefox - stack based
V8 para Chrome/Opera/Edge Chromium/Node.js - register based
JavaScriptCore (também Nitro ou Squirrel Fish) para Safari - register based
Chakra para Edge antigo e Internet Explorer - ?? based

ActionScript

Process virtual machine (AVM2)

Python

Interpretada (versão oficial sem just in time compiler)
Process virtual machine (PVM)
Stack based

PHP

Versões mais novas usams Zend Virtual Machine, mas o código é recompilado a cada execução

VBA / VB6

Nativa compilada
Pode ser executada em modo interpretado

Ada

Nativa compilada

Object Pascal (Delphi)

Nativa compilada

Ruby

Process virtual machine (YARV)
Stack based vm

Smalltalk

Interpretada

Common Lisp

Interpretada

Haskell

Nativa compilada via GHC (realiza transpilação, depois compilação) ou interpretada

F#

Web Assembly text format

Stack based vm

LLVM IR

Instruções baixo nível que serão compiladas

Assembly

Nativa compilada
  1. a

A

Comentários e documentação inline

Comentários básicos

Rust

// linha /* bloco */ fn someFunction(/* bloco */ arg1:i32) -> i32 { 0 }

Go

// linha /* bloco */ func someFunction(/* bloco */ x int) int { return 0 }

C++

// linha /* bloco */ int someFunction(/* bloco */ int arg) { return 0; }

Objective-C

// linha /* bloco */ int someFunction(/* bloco */ int arg) { return 0; } @implementation SomeClass - (int) someMethod /* bloco */ :(int)arg { return 0; } @end

Swift

// linha /* bloco */ func someFunction(/* bloco */ arg1:Int) -> Int { return 0 }

Kotlin

// linha /* bloco */ fun someFunction(/* bloco */ arg:Int): Int { return 0 }

Java

// linha /* bloco */ int someMethod(/* bloco */ int arg) { return 0; }

C#

// linha /* bloco */ int someFunction(/* bloco */ int arg) { return 0; }

Dart

// linha /* bloco */ int someFunction(/* bloco */ int arg) { return 0; }

TypeScript

// linha /* bloco */ function someFunction(/* bloco */ arg:number):number { return 0; }

JavaScript

// linha /* bloco */ function someFunction(/* bloco */ arg) { return 0; }

ActionScript

// linha /* bloco */ function someFunction(/* bloco */ arg:int):int { return 0; }

Python

# linha """ string sendo usada como comentário de bloco """ # Django also # supports {# your comment #} # and {% comment "your comment" %} # as a block comment

PHP

// linha # linha /* bloco */ function someFunction(/* bloco */ int $arg):int { return 0; }

VBA / VB6

' linha

Ada

-- linha

Object Pascal (Delphi)

// linha { bloco } (* bloco *)

Ruby

# linha =begin bloco o end precisa ocupar uma linha separada =end # ruby on rails also # supports <%# comment %> # as a block comment

Smalltalk

"bloco"

Common Lisp

; linha #| bloco |#

Haskell

-- linha {- bloco -}

F#

// linha (* bloco *) let someFunction (* bloco *) _x = 0

Web Assembly text format

;; linha

LLVM IR

; linha

Assembly

; linha

Comentários aninhados

Rust

/* bloco /* bloco aninhado */ bloco */

Go

-

C++

-

Objective-C

-

Swift

/* bloco /* bloco aninhado */ bloco */

Kotlin

-

Java

-

C#

-

Dart

/* bloco /* bloco aninhado */ bloco */

TypeScript

-

JavaScript

-

ActionScript

-

Python

-

PHP

-

VBA / VB6

-

Ada

-

Object Pascal (Delphi)

// Turbo Pascal and Delphi do not support // Free Pascal supports it // better not use

Ruby

-

Smalltalk

-

Common Lisp

#| bloco #| bloco aninhado |# bloco |#

Haskell

{- bloco {- bloco aninhado -} bloco -}

F#

-

Web Assembly text format

-

LLVM IR

-

Assembly

-

Agrupamentos

Rust

// region idea intellij foldable // endregion

Go

// TODO talvez seja suportado // por GoLand ou extensão // do VS Code

C++

#pragma region vscode foldable #pragma endregion

Objective-C

#pragma mark - XCode section with dash #pragma mark XCode section

Swift

// MARK: - XCode section with dash // MARK: XCode section

Kotlin

// region idea intellij foldable // endregion

Java

// region idea intellij foldable // endregion // #region vs code foldable // #endregion

C#

#region foldable #endregion

Dart

// region idea intellij foldable // endregion // #region vs code foldable // #endregion

TypeScript

// #region vs code foldable // #endregion

JavaScript

// #region vs code foldable // #endregion

ActionScript

// Adobe Animate/Flash and FlashDevelop // are able to collapse any scope or // selected portions of the source code // #region vs code foldable // #endregion

Python

#region foldable (pycharm, visual studio and vs code) #endregion

PHP

VBA / VB6

#Region vs code foldable #End Region

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

Assembly

Documentação de folding do VS Code.

Documentação inline

Rust

/// Rustdoc para o item que segue **com markdown** /// # Arguments /// * `arg1` - The argument of the function /// # Examples /// ``` /// let result = some_function(2); /// ``` fn some_function(arg1:i32) -> i32 { 0 } mod foo { //! Rustdoc para o contêiner externo }

Go

// someFunction Comentários simples logo antes das declarações func someFunction(/* bloco */ x int) int { return 0 }

C++

/// <summary>Visual Studio XML Documentation alt 1</summary> /// <param>The argument of the function</param> /// <returns>The result of the function call</returns> /// <example> /// <code> /// auto result{someFunction(2)}; /// </code> /// </example> int someFunction(int arg) { return 0; } /** <summary>Visual Studio XML Documentation alt 2</summary> <param>The argument of the function</param> <returns>The result of the function call</returns> <example> <code> auto result{someFunction(2)}; </code> </example> */ int someFunction(int arg) { return 0; } /// XCode Doxygen / Header Doc alt 1 /// \param arg The argument of the function /// \returns The result of the function call /// \code /// auto result{someFunction(2)}; int someFunction(int arg) { return 0; } //! XCode Doxygen / Header Doc alt 2 //! @param arg The argument of the function //! @return The result of the function call //! @code //! auto result{someFunction(2)}; int someFunction(int arg) { return 0; } /** XCode Doxygen / Header Doc alt 3 \param arg The argument of the function \return The result of the function call \code auto result{someFunction(2)}; */ int someFunction(int arg) { return 0; } /*! XCode Doxygen / Header Doc alt 4 @param arg The argument of the function @returns The result of the function call @code auto result{someFunction(2)}; */ int someFunction(int arg) { return 0; }

Objective-C

// C style /// XCode Doxygen / Header Doc alt 1 /// \param arg The argument of the function /// \returns The result of the function call /// \code /// int result = someFunction(2); int someFunction(int arg) { return 0; } //! XCode Doxygen / Header Doc alt 2 //! @param arg The argument of the function //! @return The result of the function call //! @code //! int result = someFunction(2); int someFunction(int arg) { return 0; } /** XCode Doxygen / Header Doc alt 3 \param arg The argument of the function \return The result of the function call \code int result = someFunction(2); */ int someFunction(int arg) { return 0; } /*! XCode Doxygen / Header Doc alt 4 @param arg The argument of the function @returns The result of the function call @code int result = someFunction(2); */ int someFunction(int arg) { return 0; } // Objective-C style @implementation SomeClass /// XCode Doxygen / Header Doc alt 1 /// \param arg The argument of the function /// \returns The result of the function call /// \code /// SomeClass *someObject = [SomeClass alloc]; /// int result = [someObject someMethod:2]; - (int) someMethod /* bloco */ :(int)arg { return 0; } //! XCode Doxygen / Header Doc alt 2 //! @param arg The argument of the function //! @return The result of the function call //! @code //! SomeClass *someObject = [SomeClass alloc]; //! int result = [someObject someMethod:2]; - (int) someMethod /* bloco */ :(int)arg { return 0; } /** XCode Doxygen / Header Doc alt 3 \param arg The argument of the function \return The result of the function call \code SomeClass *someObject = [SomeClass alloc]; int result = [someObject someMethod:2]; */ - (int) someMethod /* bloco */ :(int)arg { return 0; } /*! XCode Doxygen / Header Doc alt 4 @param arg The argument of the function @returns The result of the function call @code SomeClass *someObject = [SomeClass alloc]; int result = [someObject someMethod:2]; */ - (int) someMethod /* bloco */ :(int)arg { return 0; } @end

Swift

/** XCode markdown - Parameter arg1: The argument of the function - Returns: The result of the function call let result = someFunction(2) */ func someFunction(arg1:Int) -> Int { return 0 }

Kotlin

/** KDoc {@code var result = someFunction() } @param arg1 The argument of the function @return The result of the function call */ fun someFunction(arg1:Int):Int { return 0 }

Java

public class SomeClass { /** JavaDoc {@code SomeClass someObject = new SomeClass(); int result = someObject.someMethod(); } @param arg1 The argument of the function @return The result of the function call */ public int someMethod(int arg1) { return 0; } }

C#

public class SomeClass { /// <summary>Visual Studio XML Documentation alt 1</summary> /// <param name="arg1">The argument of the function</param> /// <returns>The result of the function call</returns> /// <example> /// <code> /// var someObject = SomeClass(); /// var result = someObject.SomeMethod(2); /// </code> /// </example> public int SomeMethod(int arg1) { return 0; } /** <summary>Visual Studio XML Documentation alt 2</summary> <param name="arg1">The argument of the function</param> <returns>The result of the function call</returns> <example> <code> var someObject = SomeClass(); var result = someObject.SomeMethod(2); </code> </example> */ public int SomeOtherMethod(int arg1) { return 0; } }

Dart

/// To reference parameter names /// in the comment we use square /// brackets [arg1] and unstructured /// text. /// /// Markdown is supported, particularly, /// examples use triple backtics /// ```dart /// min(5, 3) == 3 /// ``` int someFunction(int arg1) { return 0; }

TypeScript

JavaScript

/** JSDoc @param {number} arg1 The argument of the function @returns {number} The result of the function call @example let result = someFunction(2); */ function someFunction(arg1) { return 0; } /** para indicar overloads, usamos uma mistura de tipos e argumentos opcionais que fica com uma péssima legibilidade @param {(number|string)} arg1 número ou string @param {number} [arg2] opcional @returns {(number|string)} número ou string para cobrir a falta de suporte da linguagem para certas funcionalidades, podemos usar também @private, @override, @enum etc. */ function someFunction(arg1) { /// <signature> /// <summary>Visual Studio XML Documentation</summary> /// <param name="arg1" type="Number">The argument of the function</param> /// <returns type="Number">The result of the function call</returns> /// </signature> return 0; } // <signature> é opcional, e permite separar claramente // os overloads da função, pois podemos ter mais de uma signature

ActionScript

/** * ASDoc * <p>Html such as <code>myMethod</code> is allowed. * Notice that you do not use the paragraph tag in the * first paragraph of the description.</p> * * @param arg1 The argument of the function * @return The result of the function call * @see someOtherMethod */ function someFunction(arg1:int):int { return 0; }

Python

some_function.__doc__ = ".__doc__ guarda um texto de ajuda" def some_function(arg1: int): """Ou então logo após a linha de definição. If the argument `sound` isn't passed in, the default Animal sound is used. Parameters ---------- arg1 : int Primeiro argumento """

PHP

VBA / VB6

-

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

Assembly

  1. Objective-C / Swift / C#
  2. C++
  3. Rust / Java
  4. JavaScript

Objective-C, Swift e C# possuem ferramentas padrão nas respectivas IDEs.
C++ não possui uma ferramenta oficial. Varia de acordo com a IDE ou ferramenta externa e permite a mistura de muitos estilos e palavras alternativas.
Rust possui documentação inline padronizada, mas as possibilidades são bastante simples.
Java usa JavaDoc, que só permite documentação usando /** */. Aliado com o fato de que Java não suporta comentários de bloco aninhados, um trecho de código devidamente documentado é impossível de se comentar com /* */.
JavaScript, assim como C++ não possui padrão de documentação. Porém, o caso do JavaScript é mais grave pois as sintaxes variam bastante entre si, inclusive quanto ao seu posicionamento no código. A ferramenta mais amplamente difundida JSDoc possui sintaxe confusa quanto à overloads.

Declaração de Variáveis

Rust

let x = 5; // tipo implícito let x:i32 = 5; // tipo explícito let mut x = 5; // variável let x = 5; // constante let a:i32 = 1; let ponteiro_de_int_const:*const i32 = &a; let mut b:i32 = 1; let ponteiro_de_int_var:*mut i32 = &mut b;

Go

var x = 5 // tipo implícito var x int32 = 5 // tipo explícito x := 5 // atalho para declaração const x = 5 // constante var a = 1 var ponteiroDeInt *int = &a // ponteiro // variáveis relacionadas // podem ser declaradas juntas var ( countLock sync.Mutex inputCount uint32 outputCount uint32 errorCount uint32 )

C++

auto x{5}; // tipo implícito int x{5}; // tipo explícito int x(5); // estilo antigo int x = 5; // estilo c const int z{5}; // constante constexpr int x{5}; // expressão constante int& referenciaDeInt; // referência int* ponteiroDeInt{&x}; // ponteiro

Objective-C

int x = 5; // variável const int x = 5; // constante int* x; // ponteiro

Swift

let x = 5 // tipo implícito let x:Int = 5 // tipo explícito var x = 5 // variável let x = 5 // constante // Swift tem lazy properties declaradas com // lazy var x = ... // veja classes para exemplos dessa declaração

Kotlin

val x = 5 // tipo implícito val x:Int = 5 // tipo explícito var x = 5 // variável val x = 5 // constante // não precisa ser inicializada na declaração val x:Int x = 5 // constante em tempo de compilação // precisa ser inicializada na declaração const val x = 5

Java

var x = 5; // tipo implícito - java 10+ int x = 5; // tipo explícito int x = 5; // variável final int x = 5; // constante // não precisa ser inicializada na declaração final int x; x = 5;

C#

var x = 5; // tipo implícito int a = 5; // tipo explícito var x = 5; // variável const int x = 5; // constante // tipo ignorado em tempo de compilação dynamic x = 5; unsafe { int* ponteiroDeInt = &x; // ponteiro }

Dart

var x = 5 // tipo implícito int x = 5 // tipo explícito int x = 5; // variável final int x = 5; // assign only once constant const int x = 5; // compile time constant // não precisa ser inicializada na declaração final int x; x = 5; // lazy late int x = expensiveCall();

TypeScript

JavaScript

'use strict'; let x = 5; // variável const x = 5; // constante let x = 5; // tipo dinâmico var x = 5; // estilo antigo // lança exceção em modo estrito // mas é aceito em modo normal useSemDeclarar = 5;

ActionScript

var x = 5; // tipo dinâmico x = 'dynamic type'; var x:int = 5; // tipo explícito const x = 5; // constante const x:int = 5; // constante

Python

# não existe uma declaração explícita # erros de digitação podem introduzir bugs # indesejados... x = 5 x = 'dynamic type'

PHP

// não existe uma declaração explícita // erros de digitação podem introduzir bugs // indesejados... $x = 5; // variável const x = 5; // constante define('x', '5'); // constante $referenciaDeX =&$x; // referência global $g; // variável global // variáveis Variáveis $Bar = "a"; $Foo = "Bar"; $World = "Foo"; $Hello = "World"; $a = "Hello"; $a; // retorna Hello $$a; // retorna World $$$a; // retorna Foo $$$$a; // retorna Bar $$$$$a; // retorna a $$$$$$a; // retorna Hello $$$$$$$a; // retorna World

VBA / VB6

Option Explicit Dim x As Integer: x = 5 ' variável Const x As Integer = 5 ' constante Dim x: x = 5 ' tipo dinâmico Dim x As Variant: x = 5 ' tipo dinâmico ' lança exceção com Option Explicit ' caso contrário é aceito useSemDeclarar = 5 ' Datas tem uma literal especial, em formato americano... ' Podemos digitar no formato #yyyy-mm-dd# e a IDE troca automaticamente para nós Const dataLimite As Date = #12/30/2017#

Ada

procedure Main is -- variáveis são declaradas -- num bloco separado X:Integer := 0; -- variável Y:constant Integer := 0; -- constante begin -- variáveis são declaradas -- num bloco separado declare Y:Integer := 0; begin null; end; end Main;

Object Pascal (Delphi)

program Main; // variáveis são declaradas // num bloco separado var x:Integer = 0; // variável const y:Integer = 0; // constante begin // end.

Ruby

# não existe uma declaração explícita # erros de digitação podem introduzir bugs # indesejados... x = 0 # variável X = 0 # constante (maiúscula, lança warning apenas)

Smalltalk

"variáveis são declaradas" "num bloco separado?" |x| x := 5

Common Lisp

; variáveis (let( (x 0) (y 0) z )) (let*( (x 0) (y 0) z )) (defvar *x* 0) (defparameter *x* 0.001) ; constante (defconstant x 0 "constante")

Haskell

x <- return 0 -- variável x = 0 -- constante let x = 0 -- constante {- identificadores são declarados num bloco separado where se o escopo for local Além disso, como os identificadores nunca mudam de valor, a declaração pode ser feita depois do seu uso -} minhaFuncao paramA = paramA * valorB where -- valorB declarado depois valorB = paramA + 1

F#

let x = 0 // constante

Web Assembly text format

(module (memory $0 0) i32.const 0 )

LLVM IR

Assembly

Desestruturação

Rust

let (x, y) = (1, 2);

Go

// não suporta, mas as funções // podem retornar valores múltiplos min, max := getBounds(points)

C++

// C++ 17+ auto [x, y] = std::make_tuple(1, 2); struct Point { int x; int y; }; Point p {1, 2}; auto [x, y] = p;

Objective-C

-

Swift

let (x, y) = (1, 2)

Kotlin

var (x, y) = Pair(1, 2)

Java

-

C#

// C# 7+ (var x, var y) = (1, 2); // TODO deconstructors

Dart

// check progress

TypeScript

JavaScript

[x, y] = [1, 2];

ActionScript

-

Python

x, y = (1, 2) head, *tail = [1, 2, 3, 4, 5] a, b, *other, z = [1, 2, 3, 4, 5] a, _ = [1, 2] print(a) # Prints: 1 a, _, c = (1, 2, 3) print(a) # Prints: 1 print(c) # Prints: 3 a, *_ = [1, 2, 3, 4, 5] a, *_, b = [1, 2, 3, 4, 5] a, _, b, _, c, *_ = [1, 2, 3, 4, 5, 6]

PHP

// list() style list($x, $y) = [1, 2]; // [] style [$x, $y] = [1, 2];

VBA / VB6

-

Ada

-

Object Pascal (Delphi)

-

Ruby

x, y = 1, 2

Smalltalk

Common Lisp

(destructuring-bind (x y) (list 1 2) ;... )

Haskell

-

F#

Web Assembly text format

LLVM IR

Assembly

Nomes Válidos

Rust

let eu1:i32; let _ = "bem sucinto"; let _123 = "meio confuso"; let _if = "meio confuso"; // podemos ainda usar r# na frente // do nome pra evitar colisões // com palavras-chave e tipos let r#if = "muito confuso"; let r#int = "muito confuso"; // a diferença de r# ao invés de _ // é que r# foi introduzido para // suportar códigos de edições anteriores // por exemplo, a palavra-chave try // foi criado na edição 2018, // invalidando a macro try! da edição 2015 // que pode ser chamada com r#try! se necessário

Go

var _123 = 1 var _if = 1 var π = 3.14159 var 你好 = "你好世界" // letras unicode, números e _

C++

int eu1; auto _ = "bem sucinto"; auto _123 = "meio confuso"; auto _if = "meio confuso";

Objective-C

int eu1; int _ = "bem sucinto"; int _123 = "meio confuso"; int _if = "meio confuso";

Swift

// TODO // ignorar a variável let _ = 1 let π = 3.14159 let 你好 = "你好世界" let 🐶🐮 = "dogcow" // cannot contain // whitespace characters // mathematical symbols // arrows // private-use (or invalid) // Unicode code points // line- and box-drawing // cannot begin with a number

Kotlin

Java

int eu1; int _ = "bem sucinto"; // deprecated int _123 = "meio confuso"; int _if = "meio confuso"; int $ = "bem sucinto"; int $123 = "meio confuso"; int $if = "meio confuso"; // TODO posso usar $$ ou misturar $?

C#

int eu1; var _ = "bem sucinto"; var _123 = "meio confuso"; var _if = "meio confuso"; // podemos ainda usar @ na frente // do nome pra evitar colisões // com palavras-chave e tipos var @if = "muito confuso"; var @int = "muito confuso"; // TODO // a diferença de @ ao invés de _ // é que...

Dart

TypeScript

JavaScript

let eu1; let _ = "bem sucinto"; let _123 = "meio confuso"; let _if = "meio confuso"; // TODO misturar _ let $ = "bem sucinto"; let $123 = "meio confuso"; let $if = "meio confuso"; // TODO posso usar $$ ou misturar $? // muitos frameworks utilizam $ // como nome de seus objetos // principais // jQuery deve ser o mais // famoso

ActionScript

var eu1; var _ = 'bem sucinto'; var _123 = 'meio confuso'; var _if = 'meio confuso'; var $ = 'bem sucinto'; var $$ = 'bem sucinto'; var $123 = 'meio confuso'; var $if = 'meio confuso'; var π = 3.14159; var 你好 = "你好世界";

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

Assembly

  1. Swift
  2. Rust
  3. C#
  4. JavaScript
  5. C++
  6. Java
  7. Objective-C
  8. Python

Quem diria que um tópico tão simples seria tão diverso entre as linguagens?

Fortran usava = e ALGOL usava := para atribuir valores às variáveis. Nessa lista, apenas Ada, Object Pascal (Delphi) e Smalltalk utilizam o estilo ALGOL. Como consequência, nestas linguagens como podemos ver, usamos = para comparação, enquanto que as demais precisam usar algo como ==. Algumas linguagens como Lisp e SQL usam uma palavra-chave como set para atribuição.

Rust e Swift são quase idênticos, mudando apenas uma coisa. Swift faz a declaração de variáveis e constantes serem equivalentes, enquanto Rust faz a declaração de variávies mais difíceis que de constantes. Mas porque Swift utilizou let ao invés de const?
JavaScript é a única das linguagens comparadas que possibilita mudar os tipos das variáveis dinamicamente. Sua sintaxe de desestruturação não permite declarar e atribuir um valor ao mesmo tempo. As variáveis já devem ser declaradas antes da atribuição. JavaScript possui um estilo legado de declaracão, que cria variáveis com regras de escopo diferentes do que a maioria dos programadores espera, além de possuir um modo estrito para coibir práticas legadas.
C++ é o que tem mais legado de coisas que não deram certo, e sua última sintaxe pode ter regras mais seguras, mas certamente é bastante estranha. Tipagem implícita requer a palavra auto. Para aumentar a performance de nosso código, temos o recurso constexpr.
Java parou no tempo e Objective-C também (mas cá entre nós, a Apple pelo menos admite). Porém, Objective-c ainda tem tipos ponteiro para deixar as coisas mais confusas. Python sequer tem constantes e o sistema de tipos é dinâmico.

Null, Nullable e mônades

Rust

// não existem tipos nullable // mas existe um tipo std::Option<T> // que pode conter None ou Some() // tipo explícito let mut k:Option<i32> = None; let mut l:Option<AStruct> = None; // tipo implícito Option<i32> let mut m = None::<i32>; let mut n = Some(10); // erro, não pode passar um valor diretamente // tem que usar Some(valor) let mut o:Option<i32> = 10; // não possui operador específico para Option let p = match n { // p será do tipo i32 Some(some) => some, None => 10, }; // ok mas panic se for None let q = n.unwrap(); // q será do tipo i32

Go

*k := nil // nil para ponteiros // e tipos que não são structs, // array, slice, map, string, rune, // boolean e números

C++

std::optional<int> k; // C++17 boost::optional<int> l; // boost

Objective-C

// nil object // Nil class // NSNull singleton to represent null

Swift

// optionals devem ter o tipo especificado // em sua declaração var k:Int? = nil var l:AClass? = nil let m = l?.propriedade // m recebe nil let n = l!.propriedade // lança erro se l for nil // nil coalescing operator let o = k ?? 10 // o será do tipo Int // ok mas não é idiomático let p = k != nil ? k : 10 // p será do tipo Int? // PS: nullable é chamado de optional // e null é chamado de nil em Swift

Kotlin

// nullables devem ter o tipo especificado // em sua declaração var k:Int? = null var l:AClass? = null val m = l?.propriedade // m recebe null val n = l!!.propriedade // lança erro se l for null // null coalescing operator val o = k ?: 10 // o será do tipo Int

Java

// tipos primitivos não podem ser nullable int a = null; // erro // qualquer tipo de referência é nullable Integer k = null; AClass l = null; Integer m = (l != null) ? l.propriedade : null; // Lombok possui a anotação @NonNull Integer k = 0; // IntelliJ e Eclipse possuem uma anotação para auxiliar // na checagem de nullables @NotNull Integer k = 0; // não possui operador específico para null int n = (k != null) ? k : 10; // n aceita ser do tipo int ou Integer

C#

// nullable não pode ser usado com var // um tipo deve ser especificado int? k = null; AClass? l = null; int? m = l?.propriedade; // C# 6 int? m = x?[indice]; // C# 6 int? m = (l != null) ? l.propriedade : null; // null coalescing operator var n = k ?? 10; // n será do tipo int // ok mas não é idiomático var o = (k != null) ? k : 10; // o será do tipo int?

Dart

// nullables devem ter o tipo especificado // em sua declaração int? k = null; // TODO testar propriedades

TypeScript

// não existem tipos nullable // mas é possível declarar um union // que pode conter null e outros valores type NullableNumber = number | undefined | null; let k:NullableNumber = null; let n = l!.propriedade(); // somente em tempo de compilação

JavaScript

'use strict'; // qualquer tipo é sempre nullable let k = null; let l = (k && k.propriedade) ? k.propriedade : null; // null coalescing operator let m = k || 10; // ok mas não é idiomático let n = (k || k === 0) ? k : 10;

ActionScript

// qualquer tipo é sempre nullable var k = null; var l = (k && k.propriedade) ? k.propriedade : null; // null coalescing operator var m = k || 10; // ok mas não é idiomático var n = (k || k === 0) ? k : 10;

Python

# qualquer tipo é sempre nullable k = None

PHP

// qualquer tipo é sempre nullable $k = null;

VBA / VB6

Option Explicit ' qualquer tipo é sempre nullable ' mas o Visual Basic usa as palavras Empty e Nothing para tanto ' a palavra null é reservada para uso com bancos de dados ' Empty é o valor que uma variável não inicializada possui Dim x: x = Empty ' Nothing só é usado com objetos TODO confirmar isso

Ada

-- somente tipos access (ponteiros) -- podem ter o valor null type T_MyType_Access is access T_MyType; -- TODO

Object Pascal (Delphi)

// ponteiros podem ter o valor nil // TODO Varint pode também?

Ruby

# qualquer tipo é sempre nullable k = nil

Smalltalk

"qualquer variável é sempre nullable" |k| k := nil

Common Lisp

nil () ;; thereʼs also null, which contains nil…

Haskell

-- null em Haskell se chama bottom -- como Haskell só tem constantes -- uma constante com valor bottom -- não seria muito útil -- mas existe um tipo Maybe -- que pode conter Nothing ou Just f::Int -> Maybe Int f 0 = Nothing f x = Just x g::Int -> Maybe Int g 100 = Nothing g x = Just x h::Int -> Maybe Int h x = case f x of Just n -> g n Nothing -> Nothing h'::Int -> Maybe Int h' x = do n <- f x g n -- Haskell possui o operador >>= -- para extrair valores de Maybe -- é o operador que está na logo -- da linguagem let monad = Maybe(x) >>= f >>= \n -> g(n)

F#

Web Assembly text format

(module (memory $k 0) (export "memory" (memory $k)) )

LLVM IR

; somente ponteiros @k = global i8* null

Assembly

  1. a

A

Tipos Primitivos Boolean

Rust

// tipo bool let oitoOuOitenta = true; oitoOuOitenta = false; // converte para true oitoOuOitenta = !oitoOuOitenta; // parse let toParse = "true"; let parsed:bool = toParse.parse().unwrap();

Go

// tipo bool oitoOuOitenta := true oitoOuOitenta = false // converte para true oitoOuOitenta = !oitoOuOitenta // parse toParse := "true" parsed, err := strconv.ParseBool(toParse)

C++

// tipo bool auto oitoOuOitenta = true; oitoOuOitenta = false; // converte para true oitoOuOitenta = !oitoOuOitenta; // TODO #include <boost/spirit/include/qi_bool.hpp>

Objective-C

// tipo NSNumber wrapping BOOL NSNumber* oitoOuOitenta = @YES; // tipo BOOL BOOL oitoOuOitenta = YES; // tipo C bool bool oitoOuOitenta = true;

Swift

// tipo Bool var oitoOuOitenta = true oitoOuOitenta = false // converte para true oitoOuOitenta = !oitoOuOitenta // lame... let toParse = "true" let parsed = toParse.lowercaseString == "true"

Kotlin

// tipo Boolean var oitoOuOitenta = true oitoOuOitenta = false // converte para true oitoOuOitenta = !oitoOuOitenta // parse var toParse = "true" var parsed = toParse?.toBoolean()

Java

// tipo boolean var oitoOuOitenta = true; oitoOuOitenta = false; // converte para true oitoOuOitenta = !oitoOuOitenta; // parse var toParse = "true"; var parsed = Boolean.parseBoolean(toParse);

C#

// tipo bool var oitoOuOitenta = true; oitoOuOitenta = false; // converte para true oitoOuOitenta = !oitoOuOitenta; // parse var toParse = "true"; var parsed = Boolean.Parse(toParse); // ou var parsed = false; var success = Boolean.TryParse(toParse, out parsed);

Dart

// tipo bool var oitoOuOitenta = true; oitoOuOitenta = false; // converte para true oitoOuOitenta = !oitoOuOitenta; // lame... var toParse = 'true'; var parsed = toParse.toLowerCase() == 'true';

TypeScript

// tipo Boolean let oitoOuOitenta:boolean = true; oitoOuOitenta = false; // converte para true oitoOuOitenta = !oitoOuOitenta;

JavaScript

// tipo Boolean let oitoOuOitenta = true; oitoOuOitenta = false; // converte para true oitoOuOitenta = !oitoOuOitenta; // TODO falar de falsy e truthy e !! /* // falsy var bZero = new Boolean(0); var bNull = new Boolean(null); var bEmptyString = new Boolean(''); var bfalse = new Boolean(false); // undefined e NaN // truthy var btrueString = new Boolean('true'); var bfalseString = new Boolean('false'); var bSuLin = new Boolean('Su Lin'); var bArrayProto = new Boolean([]); var bObjProto = new Boolean({});*/

ActionScript

// tipo Boolean var oitoOuOitenta = true; oitoOuOitenta = false; // converte para true oitoOuOitenta = !oitoOuOitenta; // TODO falar de falsy e truthy e !! // falsy var bZero = new Boolean(0); var bNull = new Boolean(null); var bEmptyString = new Boolean(''); var bFalse = new Boolean(false); var bNaN = new Boolean(NaN); var bUndefined = new Boolean(undefined); // truthy var bTrueString = new Boolean('true'); var bFalseString = new Boolean('false'); var bSuLin = new Boolean('Su Lin'); var bArray = new Boolean([]); var bObj = new Boolean({}); var bInfinity = new Boolean(Infinity); var bNInfinity = new Boolean(-Infinity);

Python

# tipo Boolean oitoOuOitenta = True oitoOuOitenta = False # converte para True oitoOuOitenta = not oitoOuOitenta # falsy bZero = 0 bNone = None bEmptyString = '' bFalse = False 0.0 0j Decimal(0) Fraction(0, 1) [] - an empty list {} - an empty dict () - an empty tuple b'' - an empty bytes set() - an empty set an empty range, like range(0) objects for which obj.__bool__() returns False obj.__len__() returns 0

PHP

VBA / VB6

Dim oitoOuOitenta: oitoOuOitenta = True oitoOuOitenta = False ' converte para True oitoOuOitenta = Not oitoOuOitenta ' parse Dim toParse As String: toParse = "true" Dim parsed As Boolean: parsed = CBool(toParse)

Ada

-- Usa enums: type Boolean is (False, True); X:Boolean := True; X := False; -- converte para True X := not X; -- tricky due to letter casing ToParse: constant String := "True"; Parsed:Boolean := Boolean'Value(ToParse);

Object Pascal (Delphi)

Ruby

oitoOuOitenta = true oitoOuOitenta = false # converte para true oitoOuOitenta = !oitoOuOitenta oitoOuOitenta = (not oitoOuOitenta) # lame… toParse = "true" parsed = toParse.to_s.downcase == "true" # falsy # false # nil # truthy # everything else

Smalltalk

Common Lisp

;; t is true and nil is false (let((oitoOuOitenta t)) (setq oitoOuOitenta nil) ;; converte para t (setq oitoOuOitenta (not oitoOuOitenta)) ;; or (null) instead of (not) ;; lame… (let( (toParse "True") parsed ) (setq parsed (string-equal toParse "true")) ) )

Haskell

F#

// idiomatic // TODO let IfThenElseExpression aBool = let result = if aBool then 42 else 0 // note that the else case must be specified printfn "result=%i" result // statements + mutable let mutable oitoOuOitenta = true oitoOuOitenta <- false // converte para true oitoOuOitenta <- not false // parse // TODO

Web Assembly text format

LLVM IR

Assembly

  1. a

A

Tipos Primitivos Numéricos

Integer

Rust

Signed Integer
tipotamanho
i88 bits
i1616 bits
i3232 bits
i6464 bits
i128128 bits (experimental)

Go

Signed Integer
tipotamanho
int88 bits
int1616 bits
int3232 bits
int6464 bits
rune32 bits

C++

Signed Integer
tipotamanho
char8 bits?
short16 bits ou mais
int16 bits ou mais
long32 bits ou mais
long long64 bits ou mais
Signed Integer
tipotamanho
int8_t8 bits
int16_t16 bits
int32_t32 bits
int64_t64 bits
Signed Integer
tipotamanho
int_least8_t8 bits ou mais
int_least16_t16 bits ou mais
int_least32_t32 bits ou mais
int_least64_t64 bits ou mais
Signed Integer
tipotamanho
int_fast8_t8 bits ou mais
int_fast16_t16 bits ou mais
int_fast32_t32 bits ou mais
int_fast64_t64 bits ou mais

Objective-C

Signed Integer
tipotamanho
char8 bits
short16 bits
int32 bits
long32 ou 64 bits
long long64 bits
Signed Integer
tipotamanho
int8_t8 bits
int16_t16 bits
int32_t32 bits
int64_t64 bits
Signed Integer
tipotamanho
int_least8_t8 bits ou mais
int_least16_t16 bits ou mais
int_least32_t32 bits ou mais
int_least64_t64 bits ou mais

Swift (Obj-C)

Signed Integer
tipotamanho
CChar8 bits
CShort16 bits
CInt16 bits
CLong32 bits
CLongLong64 bits

Swift

Signed Integer
tipotamanho
Int88 bits
Int1616 bits
Int3232 bits
Int6464 bits

Kotlin

Signed Integer
tipotamanho
Byte8 bits
Short16 bits
Int32 bits
Long64 bits

Java

Signed Integer
tipotamanho
byte8 bits
short16 bits
int32 bits
long64 bits

C#

Signed Integer
tipotamanho
sbyte8 bits
short16 bits
int32 bits
long64 bits
decimal128 bits

Dart

Signed Integer
tipotamanho
int64 bits

TypeScript

JavaScript

-

ActionScript

Signed Integer
tipotamanho
int32 bits
Number64 bits

Python

-

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

Signed Integer
tipotamanho
iNN bits
i11 bit
i83886078388607 bits

Assembly

Unsigned Integer

Rust

Unsigned Integer
tipotamanho
u88 bits
u1616 bits
u3232 bits
u6464 bits
u128128 bits (experimental)

Go

Unsigned Integer
tipotamanho
uint88 bits
uint1616 bits
uint3232 bits
uint6464 bits
byte8 bits

C++

Unsigned Integer
tipotamanho
char8 bits?
unsigned short16 bits ou mais
unsigned int16 bits ou mais
unsigned long32 bits ou mais
unsigned long long64 bits ou mais
Unsigned Integer
tipotamanho
uint8_t8 bits
uint16_t16 bits
uint32_t32 bits
uint64_t64 bits
Unsigned Integer
tipotamanho
uint_least8_t8 bits ou mais
uint_least16_t16 bits ou mais
uint_least32_t32 bits ou mais
uint_least64_t64 bits ou mais
Unsigned Integer
tipotamanho
uint_fast8_t8 bits ou mais
uint_fast16_t16 bits ou mais
uint_fast32_t32 bits ou mais
uint_fast64_t64 bits ou mais

Objective-C

Unsigned Integer
tipotamanho
unsigned char8 bits
unsigned short16 bits
unsigned int32 bits
unsigned long32 ou 64 bits
unsigned long long64 bits
Unsigned Integer
tipotamanho
uint8_t8 bits
uint16_t16 bits
uint32_t32 bits
uint64_t64 bits
Unsigned Integer
tipotamanho
uint_least8_t8 bits ou mais
uint_least16_t16 bits ou mais
uint_least32_t32 bits ou mais
uint_least64_t64 bits ou mais

Swift (Obj-C)

Unsigned Integer
tipotamanho
CUnsignedChar8 bits
CUnsignedShort16 bits
CUnsignedInt16 bits
CUnsignedLong32 bits
CUnsignedLongLong64 bits

Swift

Unsigned Integer
tipotamanho
UInt88 bits
UInt1616 bits
UInt3232 bits
UInt6464 bits

Kotlin

-

Java

-

C#

Unsigned Integer
tipotamanho
byte8 bits
ushort16 bits
uint32 bits
ulong64 bits

Dart

-

TypeScript

JavaScript

-

ActionScript

Unsigned Integer
tipotamanho
uint32 bits
Number64 bits

Python

-

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

Assembly

Pointer Sized Integer

Rust

Pointer Sized Integer
tipotamanho
isizeDepende do hardware
usizeDepende do hardware

Go

Pointer Sized Integer
tipotamanho
intDepende do hardware
uintDepende do hardware
uintptrDepende do hardware

C++

Pointer Sized Integer
tipotamanho
intptr_tDepende do hardware
uintptr_tDepende do hardware

Objective-C

Pointer Sized Integer
tipotamanho
NSInteger32 ou 64 bits
NSUInteger32 ou 64 bits

Swift (Obj-C)

-

Swift

Pointer Sized Integer
tipotamanho
IntDepende do Hardware
UIntDepende do Hardware

Kotlin

-

Java

-

C#

Pointer Sized Integer
tipotamanho
nintDepende do Hardware
nuintDepende do Hardware

Dart

-

TypeScript

JavaScript

-

ActionScript

-

Python

Integer
tipotamanho
IntegerDepende do Hardware

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

Assembly

Floating Point

Rust

Floating Point (IEEE-754)
tipotamanho
f3232 bits
f6464 bits

Go

Floating Point (IEEE-754)
tipotamanho
float3232 bits
float6464 bits

C++

Floating Point
tipotamanho
float32 bits
double64 bits
Floating Point
tipotamanho
long double128 bits

Objective-C

Floating Point
tipotamanho
float32 bits
double64 bits
Floating Point
tipotamanho
long double128 bits

Swift (Obj-C)

Floating Point (IEEE-754)
tipotamanho
CFloat32 bits
CDouble64 bits

Swift

Floating Point (IEEE-754)
tipotamanho
Float32 bits
Double64 bits

Kotlin

Floating Point (IEEE 754)
tipotamanho
float32 bits
double64 bits

Java

Floating Point (IEEE 754)
tipotamanho
float32 bits
double64 bits

C#

Floating Point (IEEE 754)
tipotamanho
float32 bits
double64 bits
Floating Point
tipotamanho
decimal128 bits

Dart

Floating Point (IEEE-754)
tipotamanho
double64 bits

TypeScript

JavaScript

Floating Point (IEEE 754)
tipotamanho
Number64 bits

ActionScript

Floating Point (IEEE-754)
tipotamanho
Number64 bits

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

Floating Point (IEEE 754)
tipotamanho
half16 bits
float32 bits
double64 bits
fp128128 bits
Floating Point
tipotamanho
bfloat16 bits
x86_fp8080 bits
ppc_fp128128 bits

Assembly

Complex

Rust

-

Go

Complex
tipotamanho
complex6464 bits
complex128128 bits

C++

-

Objective-C

-

Swift (Obj-C)

-

Swift

-

Kotlin

-

Java

-

C#

-

Dart

-

TypeScript

JavaScript

-

ActionScript

-

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

-

Assembly

Tipos Numéricos Não Primitivos

Rust

Floating Point
tipotamanho
num::bigint::BigInt?
num::bigint::BigUint?

Go

C++

-

Objective-C

Numeric
tipotamanho
NSNumbercluster de tipos
CGFloat32 ou 64 bits

Swift (Obj-C)

-

Swift

Floating Point
tipotamanho
Float8080 bits

Kotlin

Numeric
tipotamanho
java.math.BigInteger?
java.math.BigDecimal?

Java

Numeric
tipotamanho
BigInteger?
BigDecimal?

C#

Numeric
tipotamanho
BigInteger?
Complex?

Dart

TypeScript

JavaScript

Numeric
tipotamanho
BigInt?

ActionScript

-

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

-

Assembly

  1. Rust
  2. Swift
  3. C#
  4. Java
  5. C++
  6. Objective-C
  7. JavaScript

Rust nomeia claramente os tipos numéricos que usa, além de usar nomes curtos.
Swift prefere ser um pouco mais conservador e utilizar nomes como Int e Double. Possui também tipos para compatibilidade com as APIs em C e Objective-C.
C# mantém os nomes herdados do C (embora seja possível criar type aliases por arquivo). Notem a inconsistência com sbyte e byte devido a esta decisão. C# possui um tipo de 128 bits. Como roda numa máquina virtual, não possui tipos com tamanhos de memória como Rust e Swift. Não sei ao certo como é feito com Native .NET.
Java não possui tipos sem sinal.
C++ possui uma leve melhoria em relação à C, mas ainda é bem extenso.
Objective-C mistura tipos de C e os próprios, fazendo uma salada só. Os tipos que ele herda de C não possuem tamanho fixo. Existe apenas a garantia de que short <= int <= long <= long long. Mesma coisa vale para float <= double <= long double. Então existem tipos de tamanho fixo criados na especificação C99 e os tipos incluídos pelo framework da Apple.
JavaScript só possui um tipo numérico.

Notem que existe uma divergência entre C++ e Objective-C e as demais linguagens em relação à nomeclatura. Para as duas linguagens, int e long possuem tamanhos diferentes das demais. Por isso, ponto para as linguagens que indicam explicitamente o tamanho dos tipos no próprio nome.

Boxing de Tipos Primitivos Numéricos

Rust

-

Go

C++

-

Objective-C

Numeric
tipoclasse
?NSNumber

Swift

-

Kotlin

Signed Integer
tipoclasse
byteByte
shortShort
intInteger
longLong
Floating Point (IEEE 754)
tipoclasse
floatFloat
doubleDouble

Java

Signed Integer
tipoclasse
byteByte
shortShort
intInteger
longLong
Floating Point (IEEE 754)
tipoclasse
floatFloat
doubleDouble

C#

Signed Integer
tipostruct
sbyteSByte
shortInt16
intInt32
longInt64
decimalDecimal
Unsigned Integer
tipoclasse
byteByte
ushortUInt16
uintUInt32
ulongUInt64
Floating Point (IEEE 754)
tipoclasse
floatSingle
doubleDouble
Floating Point
tipoclasse
decimalDecimal

Dart

TypeScript

JavaScript

-

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

-

Assembly

  1. a

A

Literais Numéricas

Decimais Inteiros

Rust

// i8 let i81 = 1_i8; let i82 = -1i8; // u8 let u81 = 1_u8; // i16 let i161 = 1i16; let i162 = -1_i16; // u16 let u161 = 1u16; // i32 let i1 = 1; let i2 = -1; let i3 = 1_i32; // avisa overflow -2147483648 let i4:i32 = 2_147_483_648; let i5 = 2_147_483_648_i32; let i6 = 2_147_483_648; // avisa underflow 2147483647 let i7:i32 = -2_147_483_649; let i8 = -2_147_483_649_i32; let i9 = -2_147_483_649; // u32 let u1 = 2_147_483_648_u32; // i64 let i641 = 1_i64; let i642 = -1_i64; // u64 let u641 = 1_u64; // pointer size let isize1 = 1_isize; let usize1 = 1_usize;

Go

// pointer size i1 := 1 i2 := 2_147_483_648 // se x64 ok i3 := -2_147_483_649 // se x64 ok // lança exceção // contant ix overflows int32 var i4 int32 = 2_147_483_648 var i5 int32 = -2_147_483_649 // lança exceção // contant e1 overflows int e1 := 9_223_372_036_854_775_808

C++

// int32_t (x64 LP64) auto i1{1}; auto i2{-1}; // uint32_t (x64 LP64) auto u1{1u}; auto u2{2'147'483'648U}; // int64_t (x64 LP64) auto l1{2'147'483'648}; auto l2{-2'147'483'649}; auto l3{1l}; auto l4{1L}; auto l5{1ll}; auto l6{1LL}; // uint64_t (x64 LP64) auto ul1{9'223'372'036'854'775'808}; auto ul2{1ul}; auto ul3{1UL}; auto ul4{1ull}; auto ul5{1ULL};

Objective-C

// TODO NSNumber* myBool = @YES; NSNumber* myBool = [[NSNumber alloc] initWithBOOL:YES]; // int NSInteger i1 = 42; // NSLog(@"%zd", i1); NSNumber* i2 = @42; // NSLog(@"%@", i2); NSNumber* i3 = [[NSNumber alloc] initWithInt:42]; // uint NSUInteger u1 = 42u; // NSLog(@"%tu", u1); NSNumber* u2 = @42u; // NSLog(@"%@", u2); NSNumber* u3 = [[NSNumber alloc] initWithUnsignedInt:42u]; // long NSNumber* l1 = @42L; NSNumber* l1 = [[NSNumber alloc] initWithLong:42L]; // long long NSNumber* ll1 = @42LL; NSNumber* ll1 = [[NSNumber alloc] initWithLong:42LL];

Swift

// Int (x64) let i1 = 1 let i2 = -1 let i3 = 2_147_483_648 let i4 = -2_147_483_649 // UInt (x64) let u1:UInt = 9_223_372_036_854_775_808 // lança exceção // does not fit inside Int (x64) let e1 = 9_223_372_036_854_775_808

Kotlin

// Int val i1 = 1 val 12 = -1 val i3 = 2_147_483_648 val i4 = -2_147_483_649 // Long val l1 = 1L

Java

// int Object i1 = 1; Object i2 = -1; // long Object l1 = 2_147_483_648l; Object l2 = -2_147_483_649L; Object l3 = 1l; Object l4 = 1L; // lança exceção // integer number too large Object l5 = 9_223_372_036_854_775_808L;

C#

// int var i1 = 1; var i2 = -1; // uint var u1 = 1u; var u2 = 2147483648U; var u3 = 2147483648; // long var l1 = 2147483648L; var l2 = -2147483649; var l3 = -2147483649L; var l4 = 1l; var l5 = 1L; // ulong // terminal com ul ou lu // TODO

Dart

// TODO // int var i1 = 1; var i2 = -1; var i3 = 2147483648; var i4 = -2147483649; var u1 = 9223372036854775808; // lança exceção? // ? var e1 = 9223372036854775808;

TypeScript

JavaScript

let i1 = 1n;

ActionScript

var i1 = 1; // Number var i2:int = 2147483648; // overflows var i3 = 2147483648; // Number // avisa underflow 2147483647 var i4:int = -2147483649; // underflows var i5 = -2147483649; // Number // u32 var u1:uint = 2147483648;

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

Assembly

Decimais Floating Point

Rust

// f32 (float) let f1 = 1f32; // f64 (double) let d1 = 1f64; let d2 = 1.0;

Go

// float32 f1 := float32(1) // float64 d1 := 1.0 d2 := .7

C++

Objective-C

// NSNumber wrapping float NSNumber* f1 = @1f; NSNumber* f1m = [NSNumber numberWithFloat:1f]; // NSNumber wrapping double NSNumber *d1 = @1.0; NSNumber *d1m = [NSNumber numberWithDouble:1.0];

Swift

// Float let f1:Float = 1 // Double let d1 = 1.0 let d2 = 0.7 // não aceita .7

Kotlin

// Float val f1 = 1f val f2 = 1F // Double val d1 = 1.0 val d2 = .7

Java

// float Object f1 = 1f; Object f2 = 1F; // double Object d1 = 1d; Object d2 = 1D; Object d3 = 1.0; Object d4 = .7;

C#

// float var f1 = 1f; var f2 = 1F; // double var db1 = 1d; var db2 = 1D; var db3 = 1.0; var db4 = .7; // decimal var dc = 1m;

Dart

TypeScript

JavaScript

// double let d1 = 1; let d2 = -1; let d3 = 2147483648; let d4 = -2147483649; let d5 = 1.0; let d6 = .7;

ActionScript

// double var d1 = 1; var d2 = -1; var d3 = 2147483648; var d4 = -2147483649; var d5 = 1.0; var d6 = .7;

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

Assembly

Notações

Rust

// notação científica let c1 = 1e_0; let c2 = 1e-1; let c3 = -0.7_e-2; // notação binária let b1 = 0b_0000_0001; let b2 = -0b0000_0010; // notação octal let o1 = 0o_01234567; let o2 = -0o1234567; // notação hexadecimal let cor = 0x_ff_00_00; let x1 = -0x0123456789ABCDEF; // TODO misturar notações // com sufixos

Go

// notação científica c1 := 1e0 c2 := 1e-1 c3 := -.7e-2 // notação binária b1 := 0b_0000_0001 b2 := -0B0000_0010 // notação octal o1 := 0o_01234567 o2 := -0O1234567 // notação hexadecimal cor := 0x_ff_00_00 x1 := -0X0123456789ABCDEF // notação hexadecimal científica xc1 := 0x1p-2 // == 0.25 xc2 := 0x2.p10 // == 2048.0 xc3 := 0x1.Fp+0 // == 1.9375

C++

Objective-C

Swift

// notação científica let c1 = 1e0 let c2 = 1e-1 let c3 = -0.7_e-2 // notação binária let b1 = 0b0000_0001 let b2 = -0b0000_0010 // notação octal let o1 = 0o01234567 let o2 = -0o1234567 // notação hexadecimal let cor = 0xff_00_00 let x1 = -0x0123456789ABCDEF // notação hexadecimal científica let xc1 = 0xff0000p0 let xc2 = -0x0123456789ABCDEF_p9

Kotlin

// notação científica val c1 = 1e0 val c2 = 1e-1 val c3 = -.7e-2 // notação binária val b1 = 0b0000_0001 val b2 = -0B0000_0010 // notação hexadecimal val cor = 0xff_00_00 val x1 = -0X0123456789ABCDEF

Java

// notação científica double c1 = 1e0; double c2 = 1e-1; double c3 = -.7e-2; // notação binária int b1 = 0b0000_0001; int b2 = -0B00000010; // notação octal int o1 = 01_234_567; int o2 = -01234567; // notação hexadecimal int cor = 0xff_00_00; int x1 = -0X0123456789ABCDEF; // TODO misturar notações // com sufixos

C#

// notação científica double c1 = 1e0; double c2 = 1e-1; double c3 = -.7e-2; // notação binária - C# 7+ val b1 = 0b0000_0001 val b2 = -0B0000_0010 // notação hexadecimal int cor = 0xff0000; int x1 = -0X0123456789ABCDEF; // TODO misturar notações // com sufixos

Dart

TypeScript

JavaScript

// notação científica let c1 = 1e0; let c2 = 1e-1; let c3 = -.7e-2; // notação binária let b1 = 0B0000_0001; let b2 = -0b0000_0010; // notação octal let o1 = 0o0123_4567; let o2 = -0O123_4567; // notação hexadecimal let cor = 0xff_00_00; let x1 = -0X0123456789ABCDEF; // separadores _ requerem // Chrome 75+ // Firefox 70+ // Safari 13+

ActionScript

// notação científica var c1 = 1e0; var c2 = 1e-1; var c3 = -.7e-2; // ignora leading zeroes var i1 = 01234567; var i2 = -01234567; // notação hexadecimal var cor = 0xff0000; var x1 = -0X0123456789ABCDEF;

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

Assembly

Padding

Rust

let i1 = 10; let p1 = 01; let p2 = 00.1;

Go

i1 := 10 // desde go 1.13, antes era // considerado octal p1 := 01 p2 := 00.1

C++

// números começando com 0 // são considerados notação // octal

Objective-C

Swift

let i1 = 10 let p1 = 01 let p2 = 00.1

Kotlin

val p2 = 00.1

Java

// números começando com 0 // são considerados notação // octal

C#

var i1 = 10; var p1 = 01; var p2 = 00.1;

Dart

TypeScript

JavaScript

let i1 = 10; let p1 = 01;

ActionScript

var i1 = 10; var p1 = 01; var p2 = 00.1;

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

Assembly

  1. a

A

Conversão entre Tipos Numéricos

Operações

Rust

// Requer compilação com flag -O // Compilações sem otimização panic no overflow let i32_1:i32 = 2; let i32_2:i32 = 4; let i32_min:i32 = std::i32::MIN; let i32_max:i32 = std::i32::MAX; let i64_1:i64 = i32_max as i64; // explicit conversion 2147483647 (i64) let i16_1:i16 = i32_max as i16; // explicit conversion -1 (i16) // explicit conversion let adicao1 = i32_max + 1; // -2147483648 (i32) let adicao2 = i64_1 + (i32_1 as i64); // 2147483649 (i64) let adicao3 = i64_1 + (i32_max as i64); // 4294967294 (i64) // explicit conversion let subtracao1 = i32_min - 1; // 2147483647 (i32) let subtracao2 = (i16_1 as i32) - i32_1; // -3 (i32) let subtracao3 = (i16_1 as i32) - i32_max; // -2147483648 (i32) // explicit conversion let multiplicacao1 = i32_1 * i32_2; // 8 (i32) let multiplicacao2 = i32_max * i32_1; // -2 (i32) let multiplicacao3 = (i32_1 as i64) * i64_1; // 4294967294 (i64) // explicit conversion let divisao1 = i32_2 / i32_1; // 2 (i32) let divisao2 = i32_1 / i32_2; // 0 (i32) let divisao3 = (i16_1 as i32) / i32_1; // 0 (i32) // NOTA // literais numéricas sem sufixo possuem o tipo _ // e não realizam operações matemáticas // TODO converte para char e boolean

Go

// requer import "math" // integer literals without type are int by default, not int32 var i32_1 int32 = 2 var i32_2 int32 = 4 var i32_min int32 = math.MinInt32 var i32_max int32 = math.MaxInt32 i64 := int64(i32_max) // explicit conversion 2147483647 (int64) i16 := int16(i32_max) // explicit conversion -1 (int16) // implicit conversion adicao1 := i32_max + 1 // 2147483648 (int64) subtracao1 := i32_min - 1 // -2147483649 (int64) // explicit conversion adicao2 := i64 + int64(i32_1) // 2147483649 (int64) adicao3 := i64 + int64(i32_max) // 4294967294 (int64) subtracao2 := int32(i16) - i32_1 // -3 (int32) subtracao3 := int32(i16) - i32_max // -2147483648 (int32) // explicit conversion multiplicacao1 := i32_1 * i32_2 // 8 (int32) multiplicacao2 := i32_max * i32_1 // -2 (int32) multiplicacao3 := int64(i32_1) * i64 // 4294967294 (int64) // explicit conversion divisao1 := i32_2 / i32_1 // 2 (int32) divisao2 := i32_1 / i32_2 // 0 (int32) divisao3 := int32(i16) / i32_1 // 0 (int32) intVar := 1 doubleVar := 0.1 // requer conversão explícita somaVar := float64(intVar) + doubleVar doubleVar += float64(intVar) // não requer somaLiteral := 1 + 0.1 doubleVar += 1

C++

Objective-C

Swift

// Conversão explícita é sempre requerida para // operações com variáveis let i32_1:Int32 = 2 let i32_2:Int32 = 4 let i32_min:Int32 = Int32.min let i32_max:Int32 = Int32.max let i64:Int64 = Int64(i32_max) // explicit conversion 2147483647 (Int64) let i16:Int16 = Int16(truncatingBitPattern: i32_max) // explicit conversion -1 (Int16) // explicit conversion and overflow operator &+ var adicao1 = i32_max &+ 1 // -2147483648 (Int32) var adicao2 = i64 + Int64(i32_1) // 2147483649 (Int64) var adicao3 = i64 + Int64(i32_max) // 4294967294 (Int64) // explicit conversion and overflow operator &- var subtracao1 = i32_min &- 1 // 2147483647 (Int32) var subtracao2 = Int32(i16) &- i32_1 // -3 (Int32) var subtracao3 = Int32(i16) &- i32_max // -2147483648 (Int32) // explicit conversion and overflow operator &* var multiplicacao1 = i32_1 * i32_2 // 8 (Int32) var multiplicacao2 = i32_max &* i32_1 // -2 (Int32) var multiplicacao3 = Int64(i32_1) * i64 // 4294967294 (Int64) // explicit conversion var divisao1 = i32_2 / i32_1 // 2 (Int32) var divisao2 = i32_1 / i32_2 // 0 (Int32) var divisao3 = Int32(i16) / i32_1 // 0 (Int32) // NOTA // Literais numéricas não possuem tipo específico, // apenas variáveis possuem. Portanto realizar // operações com variáveis requer conversões // explícitas, enquanto que operações com literais // não requer let intVar = 1 var doubleVar = 0.1 // requer conversão explícita let somaVar = Double(intVar) + doubleVar doubleVar += Double(intVar) // não requer let somaLiteral = 1 + 0.1 doubleVar += 1

Kotlin

Java

int i32_1 = 2; int i32_2 = 4; int i32_min = Integer.MIN_VALUE; int i32_max = Integer.MAX_VALUE; long i64 = i32_max; // implicit conversion 2147483647 (long) short i16 = (short)i32_max; // explicit conversion -1 (short) // usa o tipo maior Object adicao1 = i32_max + 1; // -2147483648 (int) Object adicao2 = i64 + i32_1; // 2147483649 (long) Object adicao3 = i64 + i32_max; // 4294967294 (long) // usa o tipo maior Object subtracao1 = i32_min - 1; // 2147483647 (int) Object subtracao2 = i16 - i32_1; // -3 (int) Object subtracao3 = i16 - i32_max; // -2147483648 (int) // usa o tipo maior Object multiplicacao1 = i32_1 * i32_2; // 8 (int) Object multiplicacao2 = i32_max * i32_1; // -2 (int) Object multiplicacao3 = i32_1 * i64; // 4294967294 (long) // usa o tipo maior Object divisao1 = i32_2 / i32_1; // 2 (int) Object divisao2 = i32_1 / i32_2; // 0 (int) Object divisao3 = i16 / i32_1; // 0 (int) // TODO char converte tb

C#

unchecked { int i32_1 = 2; int i32_2 = 4; int i32_min = Int32.MinValue; int i32_max = Int32.MaxValue; long i64 = i32_max; // implicit conversion 2147483647 (long) short i16 = (short)i32_max; // explicit conversion -1 (short) // usa o tipo maior var adicao1 = i32_max + 1; // -2147483648 (int) var adicao2 = i64 + i32_1; // 2147483649 (long) var adicao3 = i64 + i32_max; // 4294967294 (long) // usa o tipo maior var subtracao1 = i32_min - 1; // 2147483647 (int) var subtracao2 = i16 - i32_1; // -3 (int) var subtracao3 = i16 - i32_max; // -2147483648 (int) // usa o tipo maior var multiplicacao1 = i32_1 * i32_2; // 8 (int) var multiplicacao2 = i32_max * i32_1; // -2 (int) var multiplicacao3 = i32_1 * i64; // 4294967294 (long) // usa o tipo maior var divisao1 = i32_2 / i32_1; // 2 (int) var divisao2 = i32_1 / i32_2; // 0 (int) var divisao3 = i16 / i32_1; // 0 (int) } // conversão implícita se o número couber no outro // byte -> int, uint ou float por exemplo // sbyte -> int ou float // conversão explícita // entre integrals // entre floats // de floats para integrals // tipo numerico não converte pra char /* When you convert from a double or float value to an integral type, the value is truncated. If the resulting integral value is outside the range of the destination value, the result depends on the overflow checking context. When you convert double to float, the double value is rounded to the nearest float value. If the double value is too small or too large to fit into the destination type, the result will be zero or infinity. When you convert decimal to float or double, the decimal value is rounded to the nearest double or float value. */

Dart

TypeScript

JavaScript

'use strict'; // só usa um único tipo numérico double // não há o que converter // números não sofrem overflow nem underflow, // e não dão aviso se você tentar passar // dos limites let i = Number.MAX_VALUE; let j = Number.MAX_VALUE + 1; // não dá aviso if (i === j) { console.log('j foi limitado'); } i = -i j = -j - 1; // não dá aviso if (i === j) { console.log('j foi limitado'); }

ActionScript

var i32_1:int = 2; var i32_2:int = 4; var i32_min:int = int.MIN_VALUE; var i32_max:int = int.MAX_VALUE; var n_max:int = Number.MAX_VALUE; var i64_1:Number = i32_max as Number; // explicit conversion 2147483647 (Number) var i32cast_1:int = (n_max as int); // explicit conversion 0 (int) // explicit conversion var adicao1 = i32_max + 1; // 2147483648 (Number) var adicao2 = i64_1 + (i32_1 as Number); // 2147483649 (Number) var adicao3 = i64_1 + (i32_max as Number); // 4294967294 (Number) // explicit conversion var subtracao1 = i32_min - 1; // -2147483649 (Number) var subtracao2 = (i32cast_1 as Number) - i32_1; // -2 (Number) var subtracao3 = (i32cast_1 as Number) - i32_max; // -2147483647 (Number) // explicit conversion var multiplicacao1 = i32_1 * i32_2; // 8 (int) var multiplicacao2 = i32_max * i32_1; // 4294967294 (Number) var multiplicacao3 = (i32_1 as Number) * i64_1; // 4294967294 (Number) // explicit conversion var divisao1 = i32_2 / i32_1; // 2 (int) var divisao2 = i32_1 / i32_2; // 0.5 (Number) var divisao3 = (i32cast_1 as Number) / i32_1; // 0 (Number) var divisao4 = (i32_2 as Number) / i32_1; // 2 (Number)

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

Assembly

Argumentos

Rust

Go

C++

Objective-C

Swift

Kotlin

Java

/* { // conversão explícita de int para byte 1 this.recebeByte((byte)1); // conversão explícita 44 this.recebeByte((byte)300); } private void recebeByte(byte numero) { System.out.println("\nRecebe byte"); System.out.println(numero); } */

C#

Dart

TypeScript

JavaScript

// só usa um único tipo numérico double // não há o que converter

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

Assembly

Parsing de números

Rust

let i = s.parse::<i32>().unwrap(); let i:i32 = s.parse().unwrap(); let i:i32 = s.parse::<i32>().unwrap_or(0); let i = match s.parse::<i32>() { Ok(i) => i, Err(_e) => 0, };

Go

// requer import "strconv" // "a to i" e "i to a" string <--> int base 10 i, err := strconv.Atoi("-42") s := strconv.Itoa(-42) f, err := strconv.ParseFloat("3.1415", 64) // size 64 i, err := strconv.ParseInt("-42", 10, 64) // base 10 size 64 u, err := strconv.ParseUint("42", 10, 64) // base 10 size 64

C++

auto i = std::stoi(s); // #include <string> int i; i = std::from_chars(s.data(), s.data() + s.size(), i, 10);

Objective-C

int i = [s intValue]; s.intValue; [@" 2 some non-digit characters" intValue]; // 2

Swift

let i = Int(s) ?? 0

Kotlin

val i = s.toInt()

Java

var i = Integer.parseInt(s); var i = new Integer(s).intValue();

C#

var i = int.Parse(s); var i = Convert.ToInt64(s);

Dart

TypeScript

JavaScript

parseInt('1111', 2); // base 2 parseInt(15.99, 10); parseInt('15,123', 10); parseInt('15 * 3', 10); parseInt('15e2', 10); parseInt('FXX123', 16); // dangerous, no base specified // chooses base depending on string format parseFloat('3.14'); parseFloat('314e-2'); parseFloat('0.0314E+2'); parseInt('015', 10); // but `parseInt(015, 8)` will return 13 parseFloat('3.14some non-digit characters');

ActionScript

parseInt('1111', 2); // 15 parseInt('15,123', 10); // 15 parseInt('15 * 3', 10); // 15 parseInt('15e2', 10); // 15 parseInt('FXX123', 16); // 15 parseInt('FXX123', 10); // NaN // dangerous, no base specified // chooses base depending on string format parseInt('FXX123'); // 15 parseFloat('3.14'); // 3.14 parseFloat('314e-2'); // 3.14 parseFloat('0.0314E+2'); // 3.14 parseInt('015', 10); // 15 parseInt('015', 8); // 13 parseFloat('3.14some non-digit characters'); // 3.14

Python

i = int(s)

PHP

VBA / VB6

Dim i As Integer = CInt((s))

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

Assembly

  1. a

A

Units of measurement

Check https://gmpreussner.com/research/dimensional-analysis-in-programming-languages for a much more in depth coverage of this topic.

Rust

// check macros // https://stackoverflow.com/questions/60790226/custom-literals-via-rust-macros // check libraries // https://github.com/iliekturtles/uom // https://github.com/paholg/dimensioned //

Go

-

C++

// uses boost struct length_base_dimension : base_dimension<length_base_dimension, 1> { }; struct mass_base_dimension : base_dimension<mass_base_dimension, 2> { }; struct time_base_dimension : base_dimension<time_base_dimension, 3> { }; typedef length_base_dimension::dimension_type length_dimension; typedef mass_base_dimension::dimension_type mass_dimension; typedef time_base_dimension::dimension_type time_dimension; typedef derived_dimension<length_base_dimension, 2>::type area_dimension; typedef derived_dimension<mass_base_dimension, 1, length_base_dimension, 2, time_base_dimension, -2>::type energy_dimension; struct meter_base_unit : base_unit<meter_base_unit, length_dimension, 1> { }; struct kilogram_base_unit : base_unit<kilogram_base_unit, mass_dimension, 2> { }; struct second_base_unit : base_unit<second_base_unit, time_dimension, 3> { }; typedef make_system< meter_base_unit, kilogram_base_unit, second_base_unit>::type mks_system; typedef unit<dimensionless_type, mks_system> dimensionless; typedef unit<length_dimension, mks_system> length; typedef unit<mass_dimension, mks_system> mass; typedef unit<time_dimension, mks_system> time; BOOST_UNITS_STATIC_CONSTANT(meter, length); BOOST_UNITS_STATIC_CONSTANT(meters, length); BOOST_UNITS_STATIC_CONSTANT(kilogram, mass); BOOST_UNITS_STATIC_CONSTANT(kilograms, mass); BOOST_UNITS_STATIC_CONSTANT(second, time); BOOST_UNITS_STATIC_CONSTANT(seconds, time); template<> struct base_unit_info<test::meter_base_unit> { static std::string name() { return "meter"; } static std::string symbol() { return "m"; } }; template<> struct base_unit_info<test::kilogram_base_unit> { static std::string name() { return "kilogram"; } static std::string symbol() { return "kg"; } }; template<> struct base_unit_info<test::second_base_unit> { static std::string name() { return "second"; } static std::string symbol() { return "s"; } }; Unit systems defined in this way may then be used as follows: quantity<length> L(2.0 * meters); quantity<energy> E = kilograms * pow<2>(L / seconds); quantity<length, std::complex<double> > L(std::complex<double>(3.0, 4.0) * meters); quantity<energy, std::complex<double> > E(kilograms * pow<2>(L / seconds)); const double dimless = (L/L);

Objective-C

-

Swift

-

Kotlin

-

Java

// check JSR 363 import javax.measure;

C#

-

Dart

-

TypeScript

-

JavaScript

-

ActionScript

-

Python

-

PHP

-

VBA / VB6

-

Ada

-- https://www.adacore.com/gems/gem-136-how-tall-is-a-kilogram type Mks_Type is new Long_Long_Float with Dimension_System => ( (Unit_Name => Meter, Unit_Symbol => 'm', Dim_Symbol => 'L'), (Unit_Name => Second, Unit_Symbol => 's', Dim_Symbol => 'T'), ... subtype Length is Mks_Type with Dimension => (Symbol => 'm', Meter => 1, others => 0); subtype Time is Mks_Type with Dimension => (Symbol => 's', Second => 1, others => 0); m : constant Length := 1.0; s : constant Time := 1.0; cm : constant Length := 1.0E-02; km : constant Length := 1.0E+03; min : constant Time := 60.0 * s; hour : constant Time := 60.0 * min; subtype Area is Mks_Type with Dimension => ( Meter => 2, others => 0); subtype Speed is Mks_Type with Dimension => ( Meter => 1, Second => -1, others => 0); procedure Foo is subtype Acceleration is Mks_Type with Dimension => ("m/sec^2", 1, 0, -2, others => 0); G : constant Acceleration := 9.81 * M / (S ** 2); T : Time := 10.0 * S; Distance : Length; begin Distance := 0.5 * G * T ** 2; Put (Distance, Aft => 2, Exp => 0); end Foo

Object Pascal (Delphi)

-

Ruby

-

Smalltalk

-

Common Lisp

-

Haskell

F#

[<Measure>] type kg // declaration of base unit types [<Measure>] type m [<Measure>] type s let mass = 2.0<kg> let gravity = 9.81<m/s^2> let force = mass * gravity // 19.62<kg m/s^2> [<Measure>] type N = kg m/s^2 // declaration of derived unit type let force2 = 19.62<N> // same as 'force'

Web Assembly text format

-

LLVM IR

-

Assembly

-
  1. a

A

Chars

Rust

let someChar = 'T'; // suporta 4 bytes unicode \u{0000}

Go

var someRune = 'T' // go chama de runes // suporta 4 bytes unicode \u0000

C++

auto someChar = 'T'; char oitoBits; wchar_t trintaEDoisBits; // mas no windows é só 16 bits char16_t dezesseisBits; char32_t trintaEDoisBits; char8_t oitoBits; // C++11

Objective-C

NSNumber* someChar = @'T'; NSNumber* someChar = [NSNumber numberWithChar:'T'];

Swift

// Use strings com apenas um caractere // pode usar a notação \u{n} // onde n is um número com 1 a 8 dígitos hexadecimais

Kotlin

var someChar = 'T' // suporta 2 bytes unicode '\u0000' - '\uFFFF'

Java

var someChar = 'T'; // suporta 2 bytes unicode '\u0000' - '\uFFFF' // e em alguns métodos que aceitam int pode usar até '\u10FFFF'

C#

var someChar = 'T'; // suporta 2 bytes unicode '\u0000' - '\uFFFF' // ou notação em hexadecimal '\x0000'

Dart

TypeScript

JavaScript

// só usa strings // não possui chars

ActionScript

// só usa strings // não possui chars

Python

# Usa strings com apenas um caractere

PHP

VBA / VB6

Dim someChar: someChar = Chr(0) ' suporta 8 bits até Chr(255)

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

  1. Rust
  2. C++
  3. Kotlin, Java e C#
  4. Objective-C
  5. Swift, JavaScript, Python
  6. VB6

Suporte a Unicode é o que mais pesou nesta classificação. Rust possui apenas um tipo que suporta até 32 bits, e C++ possui um para cada tamanho. Não sei até que ponto isso é vantagem. Também fiquei em dúvida se ter um tipo exclusivo para caracteres é vantajoso. Vou considerar que sim, embora não tenha feito nenhum benchmark. Objective-C possui dois tipos, o próprio e o herdado do C. Provavelmente VB6 foi descontinuado antes de existir Unicode, suportando apenas ASCII...

Strings

Rust

// tipo &str let simples = "A primeira faz \"tchan\" e só"; let calvinHarris = "how deep\nis your love"; // 2 linhas // várias linhas let josePauloPaes = "Meu amor é simples, Dora, Como a água e o pão. Como o céu refletido Nas pupilas de um cão."; // concatenação let leminski = concat!("Merda é veneno.", "No entanto, não há nada", "que seja mais bonito", "que uma bela cagada.", "Cagam ricos, cagam pobres,", "cagam reis e cagam fadas.", "Não há merda que se compare", "à bosta da pessoa amada." ); // tipo String let simples = "A primeira faz \"tchan\" e só".to_string(); let raw_string = r"escape not \n processed"; let raw_string = r#"escape not " processed"#; // can also use other delimiters if needed let integer_array = b"will be stored as an [u8] array"; let raw_integer_array = br"will be stored as an [u8] array with unescaped characters"

Go

dupla := "A segunda faz 'tchun'" rawString := `A primeira faz "tchan". A segunda faz 'tchun'` calvinHarris := "how deep\nis your love" // 2 linhas // concatenação josePauloPaes := "Meu amor é simples, Dora,\n" + "Como a água e o pão.\n" + "\n" + "Como o céu refletido\n" + "Nas pupilas de um cão." // várias linhas leminskiTemplate := `Merda é veneno. No entanto, não há nada que seja mais bonito que uma bela cagada. Cagam ricos, cagam pobres, cagam reis e cagam fadas. Não há merda que se compare à bosta da pessoa amada.` emoji := "😍" clustered := "\u1F60D" // code point clustered := "\U0001F60D" // code point bytes := "\xf0\x9f\x98\x8d" // string é imutável, então seus métodos retornam novas instâncias beeGees := strings.ReplaceAll(calvinHarris, "love", "looove") strings.ToUpper("Gritando") // retorna "GRITANDO"

C++

auto cString = "mãe d'água"; auto cStringEscape = "A primeira faz \"tchan\""; auto rawString = R"(A segunda faz "tchun")"; auto html = R"(<em class="especial">ênfase</em>)"; auto meuSeparador = R"meuSeparador(aa)meuSeparador"; auto meuSeparador = R"meuSeparador( )" )meuSeparador"; // FIXME highlighter raw string auto calvinHarris = "how deep\nis your love"; // 2 linhas auto pareceMasNaoE = "começa e \ termina na mesma linha?"; // 1 linha apenas // várias linhas auto josePauloPaes = "Meu amor é simples, Dora,\n\ Como a água e o pão.\n\ \n\ Como o céu refletido\n\ Nas pupilas de um cão."; // várias linhas auto leminski = R"(Merda é veneno. No entanto, não há nada que seja mais bonito que uma bela cagada. Cagam ricos, cagam pobres, cagam reis e cagam fadas. Não há merda que se compare à bosta da pessoa amada.)"; // concatenação // TODO

Objective-C

NSString* simples = @""; NSMutableString* mutavel = @""; char* cString = "";

Swift

let simples = "A primeira faz \"tchan\" e só" let calvinHarris = "how deep\nis your love" // 2 linhas // concatenação - única maneira de usar várias linhas antes de swift 4 let josePauloPaes = "Meu amor é simples, Dora,\n" + "Como a água e o pão.\n" + "\n" + "Como o céu refletido\n" + "Nas pupilas de um cão." // várias linhas (swift 4+) let leminskiTemplate = """Merda é veneno. No entanto, não há nada que seja mais bonito que uma bela cagada. Cagam ricos, cagam pobres, cagam reis e cagam fadas. Não há merda que se compare à bosta da pessoa amada.""" let leadingWhitespace = """ Sem leading (alinhado com a última linha) Com um tab de leading Sem leading (alinhado com a última linha) """ let multiplier = 3 let stringInterpolada = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)" let emoji = "😍"; let combined = "\u{D83D}\u{DE0D}" let clustered = "\u{1F60D}" // string é imutável, então seus métodos retornam novas instâncias let beeGees = calvinHarris.replacingOccurrences(of: "love", with: "looove") "Gritando".uppercaseString // retorna 'GRITANDO'

Kotlin

val simples = "A primeira faz \"tchan\" e só" val calvinHarris = "how deep\nis your love" // 2 linhas // concatenação val josePauloPaes = "Meu amor é simples, Dora,\n" + "Como a água e o pão.\n" + "\n" + "Como o céu refletido\n" + "Nas pupilas de um cão." // várias linhas val leminskiTemplate = """Merda é veneno. No entanto, não há nada que seja mais bonito que uma bela cagada. Cagam ricos, cagam pobres, cagam reis e cagam fadas. Não há merda que se compare à bosta da pessoa amada.""" val leadingWhitespace = """ |Sem leading | Com leading |Sem leading """.trimMargin() // caso padrão de trimMargin("|") // TODO

Java

var simples = "A primeira faz \"tchan\" e só"; var calvinHarris = "how deep\nis your love"; // 2 linhas // concatenação var josePauloPaes = "Meu amor é simples, Dora,\n" + "Como a água e o pão.\n" + "\n" + "Como o céu refletido\n" + "Nas pupilas de um cão."; // várias linhas - java 14+ var leminskiTemplate = """Merda é veneno. No entanto, não há nada que seja mais bonito que uma bela cagada. Cagam ricos, cagam pobres, cagam reis e cagam fadas. Não há merda que se compare à bosta da pessoa amada."""; var leadingWhitespace = """ Sem leading (alinhado com a última linha) Com um tab de leading Sem leading (alinhado com a última linha) """;

C#

var simples = "A primeira faz \"tchan\""; var dupla = @"A segunda faz ""tchun"""; var interpolated = $"A segunda faz \"tchun\""; var calvinHarris = "how deep\nis your love"; // 2 linhas // concatenação var josePauloPaes = "Meu amor é simples, Dora,\n" + "Como a água e o pão.\n" + "\n" + "Como o céu refletido\n" + "Nas pupilas de um cão."; // várias linhas var leminskiTemplate = @"Merda é veneno. No entanto, não há nada que seja mais bonito que uma bela cagada. Cagam ricos, cagam pobres, cagam reis e cagam fadas. Não há merda que se compare à bosta da pessoa amada."; var multiInterpolated = $@"{a} {b}"; var multiplier = 3; var stringInterpolada = $"{multiplier} times 2.5 is {multiplier * 2.5}"; var emoji = "😍"; var combined = "\uD83D\uDE0D"; var clustered = "\x1F60D"; // string é imutável, então seus métodos retornam novas instâncias var beeGees = calvinHarris.Replace("love", "looove"); "Gritando".ToUpper(); // retorna 'GRITANDO'

Dart

var s1 = 'Single quotes work well for string literals.'; var s2 = "Double quotes work just as well."; var s3 = 'It\'s easy to escape the string delimiter.'; var s4 = "It's even easier to use the other delimiter."; var s1 = 'String ' 'concatenation' " works even over line breaks."; assert(s1 == 'String concatenation works even over ' 'line breaks.'); var s2 = 'The + operator ' + 'works, as well.'; assert(s2 == 'The + operator works, as well.'); var s1 = ''' You can create multi-line strings like this one. '''; var s2 = """This is also a multi-line string."""; var s = r'In a raw string, not even \n gets special treatment.'; // These work in a const string. const aConstNum = 0; const aConstBool = true; const aConstString = 'a constant string'; // These do NOT work in a const string. var aNum = 0; var aBool = true; var aString = 'a string'; const aConstList = [1, 2, 3]; const validConstString = '$aConstNum $aConstBool $aConstString'; // const invalidConstString = '$aNum $aBool $aString $aConstList'; var sb = StringBuffer(); sb ..write('Use a StringBuffer for ') ..writeAll(['efficient', 'string', 'creation'], ' ') ..write('.'); var fullString = sb.toString();

TypeScript

JavaScript

'use strict'; let simples = 'A primeira faz "tchan"'; let dupla = "A segunda faz 'tchun'"; let duplaTemplate = `A primeira faz "tchan". A segunda faz 'tchun'`; const iara = "mãe d'água"; const modoDificil = 'O\'Reilly'; let html = '<em class="especial">ênfase</em>'; let calvinHarris = 'how deep\nis your love'; // 2 linhas let pareceMasNaoE = 'começa e \ termina na mesma linha?'; // 1 linha apenas // várias linhas let josePauloPaes = 'Meu amor é simples, Dora,\n\ Como a água e o pão.\n\ \n\ Como o céu refletido\n\ Nas pupilas de um cão.'; // várias linhas let leminskiTemplate = `Merda é veneno. No entanto, não há nada que seja mais bonito que uma bela cagada. Cagam ricos, cagam pobres, cagam reis e cagam fadas. Não há merda que se compare à bosta da pessoa amada.`; let multiplier = 3; let stringInterpolada = `${multiplier} times 2.5 is ${multiplier * 2.5}`; let emoji = '😍'; let es5 = '\uD83D\uDE0D'; // code units / surrogates let es6 = '\u{1F60D}'; // code point // string é imutável, então seus métodos retornam novas instâncias let beeGees = calvinHarris.replace('love', 'looove'); 'Gritando'.toUpperCase(); // retorna 'GRITANDO'

ActionScript

var simples = 'A primeira faz "tchan"'; var dupla = "A segunda faz 'tchun'"; const iara = "mãe d'água"; const modoDificil = 'O\'Reilly'; var html = 'ênfase'; var calvinHarris = 'how deep\nis your love'; // 2 linhas var pareceMasNaoE = 'começa e \ termina na mesma linha?'; // 1 linha apenas // concatenação var josePauloPaes = 'Meu amor é simples, Dora,\n' + 'Como a água e o pão.\n' + '\n' + 'Como o céu refletido\n' + 'Nas pupilas de um cão.'; // várias linhas var leminskiTemplate = 'Merda é veneno.\n\ No entanto, não há nada\n\ que seja mais bonito\n\ que uma bela cagada.\n\ Cagam ricos, cagam pobres,\n\ cagam reis e cagam fadas.\n\ Não há merda que se compare\n\ à bosta da pessoa amada.'; var emoji = '😍'; var es5 = '\uD83D\uDE0D'; // code units / surrogates // string é imutável, então seus métodos retornam novas instâncias var beeGees = calvinHarris.replace('love', 'looove'); 'Gritando'.toUpperCase(); // retorna 'GRITANDO'

Python

simples = 'A primeira faz "tchan"' dupla = "A segunda faz 'tchun'" iara = "mãe d'água" modoDificil = 'O\'Reilly'; # TODO verificar isso html = '<em class="especial">ênfase</em>' calvinHarris = 'how deep\nis your love'; # 2 linhas pareceMasNaoE = 'começa e \ termina na mesma linha?'; # 1 linha apenas TODO verificar isso # várias linhas josePauloPaes = 'Meu amor é simples, Dora,\n\ Como a água e o pão.\n\ \n\ Como o céu refletido\n\ Nas pupilas de um cão.'; # TODO verificar isso # várias linhas leminskiTemplate = ''' Cagam ricos, cagam pobres, cagam reis e cagam fadas. Não há merda que se compare à bosta da pessoa amada.''' # várias linhas leminskiTemplate2 = """ Cagam ricos, cagam pobres, cagam reis e cagam fadas. Não há merda que se compare à bosta da pessoa amada.""" # string é imutável, então seus métodos retornam novas instâncias beeGees = calvinHarris.replace('love', 'looove'); 'Gritando'.upper(); # retorna 'GRITANDO'

PHP

VBA / VB6

Option Explicit Dim simples As String simples = "A primeira faz ""tchan"""

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

  1. a

A

Construindo strings

Rust

// TODO melhorar isso let mut vector:Vec<_>; vector.push("Terminou."); vector.push(" Só que não"); vector .chars() .collect();

Go

var stringBuilder strings.Builder stringBuilder.WriteString("Terminou") stringBuilder.WriteString(" Só que não") stringBuilder.String()

C++

#include <sstream> std::ostringstream outputStringStream; outputStringStream << "Terminou." << " Só que não."; outputStringStream.str();

Objective-C

// TODO NSMutableString

Swift

// supostamente var string // ao invés de let string

Kotlin

var stringBuilder = new StringBuilder() stringBuilder.append("Terminou.") stringBuilder.append(" Só que não.") stringBuilder.toString()

Java

var stringBuilder = new StringBuilder(); stringBuilder.append("Terminou."); stringBuilder.append(" Só que não."); stringBuilder.toString(); // StringBuilder não é thread safe // Existe também a classe StringBuffer, que é

C#

var stringBuilder = new StringBuilder(); stringBuilder.Append("Terminou."); stringBuilder.Append(" Só que não."); stringBuilder.ToString();

Dart

TypeScript

JavaScript

-

ActionScript

-

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

  1. a

A

Arrays

Rust

let vazia:[i32; 0] = []; // uma dimensão let mut preAlocada:[i32; 10]; preAlocada = [0; 17]; let prePopulada = ["p", "r", "e"]; let prePopuladaT:[&str; 3] = ["p", "o", "p"]; const linhas:usize = 2; const colunas:usize = 4; // multidimensional let mdPreAlocada:[[u8; colunas]; linhas]; let mdPrePopulada = [ [0, 1, 2, 3], [4, 5, 6, 7] ]; preAlocada[5] = 16000; let indice0 = prePopulada[0]; let two = mdPrePopulada[0][2]; for valor in prePopulada.iter() { // } for (indice, valor) in prePopulada.iter().enumerate() { // indice e valor } let tamanho = mdPrePopulada.len(); // TODO comparar arrays

Go

vazia := [0]int{} var vazia2 [0]int // uma dimensão var preAlocada [10]int // não é possível redimensionar uma array em Go prePopulada := [3]string{"p", "r", "e"} var prePopuladaT [3]string = [3]string{"p", "o", "p"} // tem que ser constantes const linhas = 2 const colunas = 4 // multidimensional var mdPreAlocada [linhas][colunas]uint8 mdPrePopulada := [linhas][colunas]uint8 { {0, 1, 2, 3}, {4, 5, 6, 7}, // , no final não é um erro, go requer } preAlocada[5] = 16000 indice0 := prePopulada[0] two := mdPrePopulada[0][2] for indice, valor := range prePopulada { // } tamanho := len(mdPrePopulada)

C++

// TODO std::Array arrayCpp; int arrayCPreAlocada[10];

Objective-C

int arrayCPreAlocada[10]; // uma dimensão NSArray* prePopulada = @[@"p", @"r", @"e"]; NSArray* prePopuladaAntiga = [NSArray arrayWithObjects:@"o", @"l", @"d", nil]; int linhas = 2; int colunas = 4; // multi dimensional int arrayCMdPreAlocada[linhas][colunas]; int arrayCMdPrePopulada[linhas][colunas] = { {0, 1, 2, 3}, {4, 5, 6, 7} }; int arrayCMdPrePopulada2[linhas][colunas] = {0, 1, 2, 3, 4, 5, 6, 7}; for (NSString* valor in prePopulada) { // }

Swift

var vazia = [Int]() var vazia2:[Int] = [] var vazia3:Array<Int> = Array<Int>() // uma dimensão var preAlocada = [Int](count: 10, repeatedValue: 0) preAlocada = [Int](count: 17, repeatedValue: 0) var prePopulada = ["p", "r", "e"] var prePopuladaT:[String] = ["p", "o", "p"] let linhas = 2 let colunas = 4 // multi dimensional var mdPrePopulada:[[Int]] = [ [0, 1, 2, 3], [4, 5, 6, 7] ] preAlocada[5] = 16000; preAlocada[6...8] = [4, 20, 8]; let indice0 = prePopulada[0]; let two = mdPrePopulada[0, 2]; for valor in prePopulada { // } for (indice, valor) in prePopulada.enumerated() { // indice e valor } let tamanho = mdPrePopulada.count // também temos a propriedade .empty // e os métodos insert e removeAtIndex // TODO testar coisas não cobertas na documentação // comparar arrays

Kotlin

// uma dimensão var preAlocada = IntArray(10) preAlocada = IntArray(17) val linhas = 2 val colunas = 4 // multi dimensional var mdPreAlocada = Array(linhas, { IntArray(colunas) }) // TODO

Java

// uma dimensão int[] preAlocada = new int[10]; preAlocada = new int[17]; String[] prePopulada = {"p", "r", "e"}; int linhas = 2; int colunas = 4; // multi dimensional byte[][] mdPreAlocada = new byte[linhas][colunas]; byte[][] mdPrePopulada = { {0, 1, 2, 3}, {4, 5, 6, 7} }; preAlocada[5] = 16000; String indice0 = prePopulada[0]; byte two = mdPrePopulada[0][2]; for (String valor : prePopulada) { // } int tamanho = mdPrePopulada.length; // TODO comparar arrays // pode mas não faça // acho que tem pra quem vem do C float podeMasNaoFaca[]; float[][] podeMasNaoFaca = {{}}; float[] podeMasNaoFaca[] = {{}}; float podeMasNaoFaca[][] = {{}};

C#

// uma dimensão int[] preAlocada = new int[10]; preAlocada = new int[17]; String[] prePopulada = {"p", "r", "e"}; int linhas = 2; int colunas = 4; // multi dimensional byte[,] mdPreAlocada = new byte[linhas, colunas]; byte[,] mdPrePopulada = { {0, 1, 2, 3}, {4, 5, 6, 7} }; byte[][] arrayDeArraysPreAlocada = new byte[4][]; arrayDeArraysPreAlocada[0] = new byte[4]; // ... byte[][] arrayDeArraysPrePopulada = { new byte[] {0, 1, 2, 3}, new byte[] {4, 5, 6, 7} }; preAlocada[5] = 16000; String indice0 = prePopulada[0]; byte two = mdPrePopulada[0, 2]; foreach (var valor in prePopulada) { // } var tamanho = mdPrePopulada.Length // TODO exemplos com var // comparar arrays

Dart

TypeScript

JavaScript

let vazia = []; // uma dimensão let preAlocada = new Array(10); preAlocada = new Array(17); let prePopulada = ["p", "r", "e"]; let linha = 0; let coluna = 2; // multi dimensional let mdPrePopulada = [ [0, 1, 2, 3], [4, 5, 6, 7] ]; preAlocada[5] = 16000; let indice0 = prePopulada[0]; let two = mdPrePopulada[linha][coluna]; for (let valor of prePopulada) { // } let tamanho = mdPrePopulada.length; // TODO comparar arrays

ActionScript

var vazia = []; // uma dimensão var preAlocada:Array = new Array(10); preAlocada:Array = new Array(17); var prePopulada:Array = ["p", "r", "e"]; var linha:uint = 0; var coluna:uint = 2; // multi dimensional var mdPrePopulada:Array = [ [0, 1, 2, 3], [4, 5, 6, 7] ]; // O tipo Array não é capaz de restringir // o tipo de seu conteúdo. Podemos // inclusive armazenar tipos misturados // Portanto não é 100% seguro especificar // um tipo quando obtemos o valor de uma Array. preAlocada[5] = 16000; var indice0 = prePopulada[0]; var two = mdPrePopulada[linha][coluna]; for (var valor in prePopulada) { // } var tamanho = mdPrePopulada.length;

Python

PHP

VBA / VB6

Dim vazia() As Integer Dim preAlocada(9) As Integer ' Aloca espaço na array vazia ' É possível usar variáveis ao invés de literais fixas ReDim Preserve vazia(0 To 9) preAlocada(5) = 1600 Dim valor As Integer For Each valor In prePopulada ' Next

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

  1. a

A

Listas

Rust

let mut lista:Vec<i32> = vec![]; lista.push(1);

Go

var lista []int // em go se chamam slices listaPreAlocada := make([]int, 10) listaPrePopulada := := []string{"p", "r", "e"} // slices são imutáveis, assim como strings lista = append(lista, 1) listaPreAlocada = append(listaPreAlocada, 1) // Go não tem uma função para remover itens // Temos duas opções // remover um item sem manter ordem (tempo constante) // copia o último item sobre o item que vai ser removido pre[i] = pre[len(pre)-1] pre[len(pre)-1] = "" // remover um item mantendo a ordem (curva tempo n) // move todos os item para a esquerda copy(pre[i:], pre[i+1:]) pre[len(pre)-1] = "" // apaga o último item pre = pre[:len(pre)-1]

C++

std::vector<int> lista; lista.push_back(1);

Objective-C

NSMutableArray* lista;

Swift

var lista = [Int]() // arrays são "listas" lista.append(1)

Kotlin

// temos List (listOf) e MutableList (mutableListOf) var lista = mutableListOf<int>() lista.add(1)

Java

// List é uma interface com ArrayList e LinkedList List<Integer> lista = new ArrayList<Integer>(); lista.add(1);

C#

List<int> lista; lista.Add(1);

Dart

TypeScript

JavaScript

let lista = []; // arrays são "listas" lista.push(1);

ActionScript

var lista = []; // arrays são listas lista.push(1); // também temos Vector, que é tipado e tem outras otimizações var lista:Vector.<String> lista = new Vector.<String>(); var listaPreAlocada:Vector.<String> = new Vector.<String>(10); var listaTamanhoFixo:Vector.<String> = new Vector.<String>(10, true); var listaPrePopulada:Vector.<String> = new <String>['p', 'r', 'e']; listaPreAlocada.push(1); listaTamanhoFixo.push(1); // erro listaPrePopulada.push(1);

Python

PHP

VBA / VB6

Dim lista As Collection Set lista = New Collection lista.Add 1

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

  1. a

A

Stack e Heap

Rust

// TODO // &'static str statically allocated lives inside the program binary code // stack by default // heap // String // Box<T> // Vec<T> // growable on heap

Go

C++

// TODO // tipos na stack por padrão // tipos com new na heap // enums? // closures?

Objective-C

// TODO // structs na stack? // e classes? // enums? // closures? tem closures?

Swift

// TODO // primitive on stack // structs e enums value types - stack // classes and closures on the heap

Kotlin

Java

// tipos primitivos na stack int i = 10; // tipos de referência na heap String s = "Na heap"; // TODO verificar string heap Object o = new Object(); // enums tb?

C#

// tipos valor na stack // tipos primitivos na stack int i = 10; // enums na stack // structs às vezes na stack AStruct a; Point p; unsafe { byte* ponteiroDeArray = stackalloc byte[1024]; } // nullables na stack // tipos de referência na heap // class, interface, array e delegate string a = "Na heap"; // TODO verificar string heap object o = new object();

Dart

TypeScript

JavaScript

// Não existe uma definição // na especificação // A máquina virtual pode ou não // alocar tipos primitivos // e tipos de referência // tanto na stack quanto na heap

ActionScript

// Mesmo tipos primitivos // são objetos, porém // imutáveis. // não está claro se usa // stack ou não

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

  1. C++ / Rust
  2. Objective-C / Swift / C#
  3. Java
  4. JavaScript

A

Gerenciamento de memória

Rust - Ownership e Lifetimes

Go - Mark and Sweep GC

C++ - RAII

// smart pointers

Objective-C - Reference Counting

// ARC

Swift - Reference Counting

// ARC

Kotlin

Java - Mark and Sweep GC

// weak e ghost references

C# - Mark and Sweep GC

// weak references

Dart

TypeScript

JavaScript - Mark and Sweep GC

// weak maps

ActionScript

// weak references

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

  1. a

A

Apontar é feio Já dizia sua mãe

Rust

// TODO let p:*const i32 = ptr::null(); let p:*mut i32 = ptr::null(); let x = 90; let raw = &x as *const i32; let mut y = 95; let raw_mut = &mut y as *mut i32; let points_at = unsafe { *raw }; unsafe { let points_at = *raw; } use std::mem; unsafe { let a = [0u8, 0u8, 0u8, 0u8]; let b = mem::transmute::<[u8; 4], u32>(a); }

Go

intOriginal := 90 segundoIntOriginal = 95 ponteiroDeInt := &intOriginal fmt.Println(*ponteiroDeInt) // 90 ponteiroDeInt = &segundoIntOriginal fmt.Println(*ponteiroDeInt) // 95 var outroPonteiroDeInt = &intOriginal var maisUmPonteiroDeInt int* aindaMaisUmPonteiroDeInt := new(int) aindaMaisUmPonteiroDeInt = &intOriginal *ponteiroDeInt = 5 fmt.Println(*ponteiroDeInt) // 5 // TODO // const int* ponteiroDeInt = &intOriginal; // podemos atribuir endereços aleatórios de memória para ponteiros ?? // ponteiro de array // ponteiros para funções? // void* ponteiroGenerico; // int** ponteiroDePonteiro;

C++

// variável tipo ponteiro // ponteiros são nullable e podemos usar // o valor especial nullptr, que representa // um endereço de memória inválido int* newNull{nullptr}; // C++11 // versões antigas usam o valor NULL, que é 0 // por baixo dos panos, também representando // um endereço de memória inválido int* oldNull{NULL}; // old // existe ainda um tipo nullptr_t, que só pode // receber nullptr e não aceita nenhum outro valor // não imagino muitos usos para ele fora fazer // piadinhas com o Elvis ;) std::nullptr_t o_onlyNuuull{nullptr}; // C++11 // variáveis comuns tipo int int intOriginal{90}; int segundoIntOriginal{95}; // variável tipo ponteiro de int (int*) aponta // para variável comum tipo int // seu valor é um inteiro 32 ou 64 bits, representando // o endereço de memória de intOriginal, que podemos // obter usando o operador & int* ponteiroDeInt{&intOriginal}; // para acessarmos o valor da variável através // do ponteiro, usamos o operador * cout << "valor de int " << *ponteiroDeInt << endl; // 90 // se fizermos ele apontar para outra variável, seu valor muda ponteiroDeInt = &segundoIntOriginal; cout << "valor de int " << *ponteiroDeInt << endl; // 95 // também podemos pegar endereços de memória através de outros // ponteiros, pois como disse acima, seus valores são numéricos // 32 ou 64 bits int* ponteiroDeSegundoInt{ponteiroDeInt}; cout << "valor de int " << *ponteiroDeSegundoInt); // 95 // TODO // podemos atribuir enderecos aleatórios de memória para ponteiros :( // podemos marcar o ponteiro como const, mas isso // NÃO PREVINE QUE ELE APONTE PARA VARIÁVEIS DIFERENTES!!! // TODO verificar se previne a modificação dos objetos apontados const int* ponteiroConst{&intOriginal}; // 90 ponteiroConst = &segundoIntOriginal; // 95 // depois que não precisarmos mais dos ponteiros // precisamos APAGÁ-LOS ANTES QUE SAIAM DE ESCOPO, // para evitar que fiquem perdidos na memória // sem podermos acessá-los (dangling pointers) // devemos fazer isso apenas para ponteiros null // ou ponteiros de objetos alocados na heap // através do operador new delete newNull; delete oldNull; // o gerenciamento manual dos ponteiros com delete // não é recomendado, e existem classes que os apagam // automaticamente e de maneira determinística assim // que saem de escopo auto ponteiroSmart{std::make_unique<int>(1000)}; auto ponteiroSmartShared{std::make_shared<int>(1001)}; // TODO old boost smart pointers // embora isso não seja necessário para ponteiros int* // existe uma outra característica dessas classes, que // é não permitir o valor nullptr, uma vez que seu tipo // é especificado auto semNullPointer{std::make_unique<int>(nullptr)}; // erro :) // embora NULL seja um valor váido para int*, uma vez que // NULL na verdade é 0 por baixo dos panos auto semNullPointer{std::make_unique<int>(NULL)}; // funciona! // além disso, não é possível mudar o endereço para o qual // esse tipo de ponteiro aponta uma segunda vez auto semSegundaChance{std::make_unique<int>(1000)}; // semSegundaChance = &intOriginal; // erro // semSegundaChance = ponteiroDeInt; // erro // TODO referências // referências não são ponteiros oficialmente segundo // a especificação // não podem ser nullptr nem NULL int& ponteiroRefNullPointer{nullptr}; // erro :) int& ponteiroRefNULL{NULL}; // erro :) int& ponteiroRef{intOriginal}; // 90 ponteiroRef = segundoIntOriginal; // 95 const int& ponteiroConstRef{intOriginal}; // 90 ponteiroConstRef = segundoIntOriginal; // erro, não é mutável :) // não pode pegar o endereço de referências // ponteiros para arrays // ponteiros para funções // void* // ponteiros de ponteiros // referências de ponteiros

Objective-C

// variável tipo ponteiro // ponteiros são nilable e podemos usar // o valor nil, que representa // um endereço de memória inválido int* nilPointer = nil; // Objective-C // é possível usar do C o valor NULL, que é 0 // por baixo dos panos, também representando // um endereço de memória inválido int* cNullPointer = NULL; // C

Swift

var nilPointer:UnsafeMutablePointer<int> = nil // variáveis comuns tipo int let intOriginal = 90 let segundoIntOriginal = 95 // int* ponteiroDeInt = &intOriginal; var ponteiroDeInt:UnsafeMutablePointer<Int> = &intOriginal print(ponteiroDeInt) // 90 ponteiroDeInt = &segundoIntOriginal print(ponteiroDeInt) // 95 let ponteiroDeSegundoInt = ponteiroDeInt print(ponteiroDeSegundoInt) // 95 // const int* ponteiroDeInt = &intOriginal; var ponteiroConst:UnsafePointer<Int> = &intOriginal ponteiroConst = &segundoIntOriginal // mais ou menos const int& ponteiroConstRef; ?? let ponteiroConstRef:UnsafePointer<Int> = &intOriginal // TODO // podemos atribuir endereços aleatórios de memória para ponteiros ?? // ponteiro de array // ponteiros para funções? // void* ponteiroGenerico; var ponteiroGenerico:UnsafePointer<Void> // int** ponteiroDePonteiro; let ponteiroDePonteiro = AutoreleasingUnsafeMutablePointer<Int?> // tem que ser nullable?

Kotlin

// possui uma classe CPointer // para interop com C apenas

Java

-

C#

using System; namespace MarcoLuglio.PonteirosExample { class MainClass { public static void Main(string[] args) { // C# requer um contexto unsafe para utilização de ponteiros // Existem vários contexto que podem ser marcados como unsafe, // mas vou mostrar apenas o bloco de código unsafe unsafe { // TODO não pode null pointer // variáveis comuns tipo int int intOriginal = 90; int segundoIntOriginal = 95; // variável tipo ponteiro de int (int*) // aponta para variável comum tipo int // seu valor é um inteiro 64 bits (long), representando // o endereço de memória de intOriginal, que podemos obter // usando o operador & int* ponteiroDeInt = &intOriginal; // para acessarmos o valor da variável comum // através do ponteiro, usamos o operador * Console.WriteLine(@"valor de int {0} ", *ponteiroDeInt); // 90 // se fizermos ele apontar para outra variável, seu valor muda ponteiroDeInt = &segundoIntOriginal; Console.WriteLine(@"valor de int {0} ", *ponteiroDeInt); // 95 // também podemos pegar endereços de memória através de outros // ponteiros, pois como disse acima, seus valores são números // tipo long int* ponteiroDeSegundoInt = ponteiroDeInt; Console.WriteLine(@"valor de int {0} ", *ponteiroDeSegundoInt); // 95 // não é possível iniciar um ponteiro especificando diretamente // um endereço de memória int* enderecoQualquer = 10; // erro TODO verificar qual o erro // variável tipo ponteiro de buffer de bytes (bytes*) // aponta para array de bytes pré-alocada na stack // seu valor é igual ao endereço de memória da array de bytes byte* ponteiroDeArray = stackalloc byte[1024]; // atribuímos o valor 5 para o índice 0 da array na stack // e o valor 11 para o índice 729 // para acessarmos os índices, usamos o operador [] ponteiroDeArray[0] = 5; ponteiroDeArray[729] = 11; // para acessarmos os valores nos índices, usamos o operador [] byte indice0 = ponteiroDeArray[0]; byte indice729 = ponteiroDeArray[729]; Console.WriteLine( @"valores {0} e {1}", indice0, // 0 indice729 // 1 ); // Notem que não há nada no ponteiro que indique se tratar de uma array! // Então como o compilador consegue diferenciar entre um ponteiro // para um byte comum e para uma array de bytes? // Ele não consegue! E dependendo do que você for fazer, nem vai lançar // uma exceção, apenas usar um valor incorreto. // Portanto cuidado ao utilizar ponteiros. // Por exemplo, seria válido (embora não recomendado) fazer isso: // byte byteOriginal = 37; // ponteiroDeArray = &byteOriginal; // variável tipo ponteiro desconhecido // aponta para qualquer tipo de variável // quando null, seu valor é igual a 0, representando um endereço // de memória inválido // neste estado, *ponteiroGenerico lança NullReferenceException void* ponteiroGenerico = null; // esse tipo de ponteiro não é recomendado pois perde // a informação sobre o tipo para o qual ele aponta // essa característica é usada para fazer casts forçados // neste estado, seu valor é igual ao endereço de memória de intOriginal ponteiroGenerico = &intOriginal; // para acessarmos o valor apontado por esse tipo de ponteiro // é necessário fazer um cast para o tipo que se deseja Console.WriteLine(@"valor de void {0} ", (*(int*)ponteiroGenerico)); // 90 // agora seu valor é igual ao endereço de memória da array de bytes ponteiroGenerico = ponteiroDeArray; // podemos acessar os valores da array apontada pelo ponteiro // fazendo o cast apropriado // a mesma recomendação sobre o operador [] vale aqui, o compilador // não consegue identificar se o valor é uma array ou um byte simples // e vai acreditar no que você pedir Console.WriteLine(@"valor de void*[0] {0} ", ((byte*)ponteiroGenerico)[0]); // 5 // variável tipo ponteiro de ponteiro de int (int**) // aponta para variável do tipo ponteiro de int // seu valor é igual ao endereço de memória de ponteiroGenerico // esse tipo de ponteiro é utilizado quando não desejamos copiar o // ponteiro original ao passá-lo para outras funções // uma vez que, como o ponteiro é um valor long, é passado por cópia // para as funções! int** ponteiroDePonteiro = (int**)&ponteiroGenerico; // para acessarmos o valor no final da cadeia, usamos o operador * duas vezes Console.WriteLine(@"valor de ponteiro {0} ", **ponteiroDePonteiro); // se usarmos apenas uma vez, obteremos o ponteiro intermediário Console.WriteLine( @"endereço apontado pelo ponteiro intermediário {0} ", *ponteiroDePonteiro ); // novamente, o compilador não pode ajudar muito caso você cometa um erro // por exemplo, se esquecermos do operador & estaremos pegando o endereço // do valor final, ao invés do endereco do ponteiro intermediário, porém, // estamos dizendo ao compilador que é o endereço de um ponteiro legítimo ponteiroDePonteiro = (int**)ponteiroGenerico; // e só será lançado um erro se tentarmos acessar o valor final na cadeia // pois estaremos tentando usar um valor inteiro como se fosse um ponteiro Console.WriteLine(@"lança NullReferenceException {0} ", **ponteiroDePonteiro); // embora possamos criar ponteiros de ponteiros de ponteiros, acho que não // há uma aplicação muito prática pra isso int*** ponteiroDesnecessario; // TODO structs e fixed {} } // os ponteiros são desalocados após o término do contexto unsafe // não é necessário deletar os ponteiros manualmente } } }

Dart

TypeScript

JavaScript

-

ActionScript

-

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

  1. Swift
  2. C++ / C#
  3. Objective-C
  4. TODO classificar rust quando tiver um exemplo mais completo

Não sei ao certo como avaliar esse tópico. Certamente não é a mesma coisa que gerenciamento de memória avaliado logo acima.
Todas as linguagens permitem void* de alguma maneira
Swift possui nomes mais claros em relação ao que cada ponteiro significa, embora a relação com suas versões em C não sejam fáceis de adivinhar. Não é necessário utilizar operadores diferentes para interagir com ponteiros.
C# tenta evitar ao máximo o uso de ponteiros para tarefas corriqueiras. Mas faz muito pouco em relação à C++ para impedir problemas com a utilização de ponteiros quando são necessários, e acaba sendo equivalente em segurança, embora de maneira diferente. As duas linguagens possuem recursos para impedir ponteiros null, e para apagar os ponteiros quando saírem de escopo. C# delimita claramente um bloco isolado para trabalhar com ponteiros, mas não permite marcá-los como const. C++ ainda tem o operador delete, mas você não precisa usá-lo.
Objective-C usa ponteiros estilo C. Requer muitas vezes que os objetos sejam alocados e depois inicializados num passo diferente. Como muitas coisas nessa linguagem, mistura sintaxes das duas linguagens. Por exemplo, ivars e properties.

Type Aliasing

Rust

// tipo simples type Name = String; // tipo função // TODO testar // type StrategyFunctionPointer = fn(i32) -> i32;

Go

// tipo simples type T1 = T2 // novo tipo baseado em T2 type T1 T2 // tipo função type StrategyFunctionPointer func(int) int

C++

// tipo simples using size_t = unsigned int; typedef unsigned char BYTE; // old // tipo função using StrategyFunctionPointer = void(*)(); // ou using StrategyFunction_t = void(); StrategyFunction_t* strategyFunctionPointer = f; // ou #include <type_traits> using StrategyFunctionPointer = std::add_pointer<void()>::type; // ou (old) typedef void(*StrategyFunctionPointer)(); // só metodos ou funções tb?

Objective-C

// tipo simples @compatibility_alias UICollectionViewController PSTCollectionViewController; typedef unsigned char BYTE; // tipo função typedef void(*StrategyFunctionPointer)();

Swift

// tipo simples typealias AudioSample = UInt16 // tipo função typealias StrategyFunctionPointer = () -> ()

Kotlin

// tipo função typealias StrategySignature = //

Java

-

C#

// tipo simples using R = N1.N2; // tipo função delegate void StrategyFunctionDelegate();

Dart

TypeScript

JavaScript

ActionScript

static const MyClass:Class = int; var ert:* = new MyClass();

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

  1. a

A

Branching / Laços

If, else if e else

Rust

Go

C++

// TODO <=>

Objective-C

Swift

Kotlin

val max = if (a > b) { a } else { b }

Java

C#

Dart

var number = 10; if (number > 0) { // positivo } else if (number < 0) { // negativo } else { // zero } // logical operators bool condition1 = true; bool condition2 = true;

TypeScript

JavaScript

ActionScript

var number:int = 10; if (number > 0) { // positivo } else if (number < 0) { // negativo } else { // zero } // logical operators var condition1:Boolean = true; var condition2:Boolean = true; // short circuit if (condition1 && condition2) { myTextField.appendText('both true'); } // short circuit if (condition1 || condition2) { myTextField.appendText('both true'); } if (condition1 != condition2) { myTextField.appendText('both true'); } if (condition1 == false) { myTextField.appendText('both true'); } if (!condition1) { myTextField.appendText('both true'); }

Python

PHP

// TODO <=>

VBA / VB6

Dim number As Integer: number = 10 If Number > 0 Then ' positivo ElseIf Number < 0 Then ' negativo Else ' zero End If ' logical operators Dim condition1 As Boolean Dim condition2 As Boolean ' short circuit If condition1 And condition2 Then ' ' short circuit If condition1 Or condition2 Then ' If condition1 Xor condition2 Then ' If condition1 <> condition2 Then ' If condition1 = False Then ' If Not condition1 Then '

Ada

declare number:Integer; begin number := 10; if number > 0 then -- positivo elsif number < 0 then -- negativo else -- zero end if; end; -- logical operators declare condition1:Bool; condition2:Bool; begin -- evaluates both conditions! if condition1 and condition2 then -- -- short circuit if condition1 and then condition2 then -- -- evaluates both conditions! if condition1 or condition2 then -- -- short circuit if condition1 or else condition2 then -- if condition1 xor condition2 then -- if condition1 /= condition2 then -- if condition1 = False then -- if not condition1 then -- end;

Object Pascal (Delphi)

var number:Integer; begin number := 10; if number > 0 then // positivo else if number < 0 then // negativo else // zero end; // ou var number:Integer; begin number := 10; if number > 0 then // positivo begin // multiline end; else if number < 0 then // negativo begin // multiline end; else // zero begin // multiline end; end; // logical operators var condition1:Bool; condition2:Bool; begin // short circuit if condition1 and condition2 then // // short circuit if condition1 or condition2 then // if condition1 xor condition2 then // if condition1 <> condition2 then // if condition1 = false then // if not condition1 then // end;

Ruby

number = 10 if number > 0 # positivo elsif number < 0 # negativo else # zero end # TODO <=> # logical condition1 = true condition2 = false # short circuit if condition1 && condition2 #... # same as && but with lower precedence if condition1 and condition2 #... # short circuit if condition1 || condition2 #... # same as || but with lower precedence if condition1 or condition2 #... if condition1 ^ condition2 #... if condition1 != condition2 #... if condition1 == false #... if !condition1 #... # same as ! but with lower precedence if not condition1 #...

Smalltalk

Common Lisp

(let( (number 10) ) ; if ; (if (condition) (then code)) ; if / else ; (if (condition) (then code) (else code)) ; if / else if... / else chain ; (if (condition) ; (then code) ; (if (else if condition) ; (then code) ; (if (else if condition) ; (then code) ; (else code) ; ))) ; close all ifs (if (> number 0) (print "positivo") ; else if (if (< number 0) (print "negativo") ; else (print "zero") )) ; TODO ; (unless) ; (when) ; (cond) )

Haskell

F#

Web Assembly text format - main.wasm

i32.const 0 ;; change to positive number (true) ;; if you want to run the if block (if (then i32.const 1 call $log ;; should log '1' ) (else i32.const 0 call $log ;; should log '0' ) ) ;; ou usar a instrução br (loop $my_loop ;; if $i is less than 10 branch to loop global.get $i i32.const 10 i32.lt_s br_if $my_loop )

LLVM IR

Assembly

while e do while

Rust

while i < 10 { // ... } let mut optional = Some(0); while let Some(i) = optional { // use i here } // mesmo que while true {...} loop { //... // to exit the loop call break; } // no do while // use loop + if break

Go

for i < 10 { // ... } // TODO testar for i := returnBoolOrNullable { // .. } // equivalente à while true {...} for { //... // to exit the loop call break; } // no do while // use for + if break

C++

Objective-C

Swift

while i < 10 { // ... } // do while repeat { // ... } while i < 10

Kotlin

while (i < 10) { // ... } do { // ... } while (i < 10) // i is visible here!

Java

C#

Dart

TypeScript

JavaScript

while (i < 10) { // ... } do { // ... } while (i < 10)

ActionScript

while (i < 10) { // ... } do { // ... } while (i < 10)

Python

while i < 10: # ... while i < 10: # ... else: # ...

PHP

VBA / VB6

While i < 10 '... Wend

Ada

while i < 10 loop -- ... end loop; -- equivalente à while true {...} loop -- ... end loop;

Object Pascal (Delphi)

while i < 10 do begin // ... end; repeat // ... until i < 10;

Ruby

while i < 10 # ... end loop do # ... end # until conditional [do] # unlike “loop do”, # here the “do” is optional until conditional # ... end

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format - main.wasm

LLVM IR

Assembly

for each

Rust

for item in collection { println!("{}", item); }

Go

slice := []int{2, 3, 4} for i, numero := range slice { // os valores dentro de for each // são cópias e não referências } dicionario := map[string]string{ "a": "apple", "b": "banana" } for chave, valor := range dicionario { // ordem não é garantida para maps } texto := "um texto" for i, letra := range texto { // } canal := make(chan int) go func() { canal <- 1 canal <- 2 canal <- 3 close(canal) }() for numero := range canal { // se o canal for fechado // for each bloqueia!? }

C++

for (const auto &item : collection) { // C++ 11+ cout >> item; } // functor com contrutor implícito struct Functor { void operator()(const Item& item) { cout >> item; } }; Functor functor(); std::for_each(collection.begin(), collection.end(), functor);

Objective-C

for(id item in collection) { NSLog(item); }

Swift

for item in collection { print(item) } let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4] for (animalName, legCount) in numberOfLegs { print("\(animalName)s have \(legCount) legs") }

Kotlin

for (item in collection) { print(item) }

Java

for (Object item : collection) { System.out.println(item); }

C#

foreach (object item in collection) { System.Console.WriteLine(item); }

Dart

TypeScript

JavaScript

for (item of collection) { console.log(item); } for (item in collection) { if (collection.hasOwnProperty(item)) { console.log(item); } }

ActionScript

for each (var item in collection) { trace(item); } for (item in collection) { trace(collection[item]); } // TODO check if behavior // is similar to JavaScript var collection:Array = ['p', 'r', 'e']; // or var collection:Vector.<Object> = new Vector.<Object>['p', 'r', 'e']; collection.forEach(function callback(item:*, index:int, arr:Array):void { trace(item.prop); // or trace(arr[index]); });

Python

collection = for n in collection: #

PHP

VBA / VB6

For Each item In collection Print item Next

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

for each + ranges

Rust

for index in 0..5 { println!("{}", x); // x: i32 }

Go

// usar range + uma coleção // não possui um operador ..

C++

// c++ 20+

Objective-C

-

Swift

for index in 0...4 { print("\(index) times 5 is \(index * 5)") } let minutes = 30 for tickMark in 0..<minutes { // render the tick mark each minute (30 times) } // range exclusivo - to let minuteInterval = 5 for tickMark in stride(from: 0, to: minutes, by: minuteInterval) { // render the tick mark every 5 minutes (0, 5, 10 ... 25) } // range inclusivo - through let minuteInterval = 5 for tickMark in stride(from: 0, through: minutes, by: minuteInterval) { // render the tick mark every 5 minutes (0, 5, 10 ... 30) }

Kotlin

for (i in 0..4) { print(i) }

Java

-

C#

-

Dart

TypeScript

JavaScript

-

ActionScript

-

Python

for n in range(0, 4, 1): #

PHP

VBA / VB6

-

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

Assembly

For

Rust

Go

C++

Objective-C

Swift

Kotlin

Java

C#

Dart

TypeScript

JavaScript

ActionScript

for (var i:int = 0; i < 3; i++) { // }

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format - main.wasm

LLVM IR

Assembly

label, goto, continue, break e switch / case / when

Rust

// label e break / continue 'loop1: for i in 0...3 { 'loop2: for j in 0...3 { if (i == 1 && j == 1) { continue 'loop1; // pode usar break tb } println!( "i = {0}, j = {1}", i, // 0 j // 1 ) } } // switch e match match x { 1 | 2 => println!("one or two"), 3...5 => println!("between three and five"), 6 => println!("six"), // default é opcional, mas se ausente // os demais cases devem ser exaustivos _ => println!("something else"), } // ver destructuring

Go

Outer: for i := 0; i < 3; i++ { for j := 0; j < 3; j++ { // continue Outer } } switch 1 { case 1: fmt.Println(1) fallthrough case 2: fmt.Println(2) }

C++

// TODO testar isso // label e goto for (int a = 0; a < 10; ++a) { for (int y = 0; y < 10; ++y) { // Run until condition. for (int x = 0; x < 10; ++x) { // Run until condition. if (x == 5 && y == 5) { goto Outer; } } ++dummy; } Outer: continue; } return dummy; switch(color) { case GREEN: case RED: case BLUE: Paint(); break; case YELLOW: if(AlsoHasCriteriaX) { Paint(); break; /* notice break here */ } goto explicit_label; case FUCHSIA: PokeEyesOut(); break; default: explicit_label: Print("Ugly color, no paint.") break; }

Objective-C

Swift

// label e break / continue loop1: for i in 0..<3 { loop2: for j in 0..<3 { if (i == 1 && j == 1) { continue loop1; // pode usar break tb } print("i = \(i), j = \(j)") } } // testar isso /*label: { // do stuff if check break label // do more stuff }*/ // switch e fallthrough switch a { case "a": // tem que ser indicado explicitamente // com a palavra fallthrough fallthrough case "A": // default: // } // switch e match switch a { case "a", "A": print("The letter A") // break é implícito // mas ainda pode ser usado // no meio de um bloco por exemplo // default é opcional, mas se ausente // os demais cases devem ser exaustivos default: print("Not the letter A") } switch approximateCount { case 0: naturalCount = "no" case 1..<5: naturalCount = "a few" default: naturalCount = "many" } switch somePoint { case (0, 0): print("\(somePoint) is at the origin") case (_, 0): print("\(somePoint) is on the x-axis") case (0, _): print("\(somePoint) is on the y-axis") case (-2...2, -2...2): print("\(somePoint) is inside the box") default: print("\(somePoint) is outside of the box") } let anotherPoint = (2, 0) switch anotherPoint { case (let x, 0): print("on the x-axis with an x value of \(x)") case (0, let y): print("on the y-axis with a y value of \(y)") case let (x, y): print("somewhere else at (\(x), \(y))") } switch yetAnotherPoint { case let (x, y) where x == y: print("(\(x), \(y)) is on the line x == y") case let (x, y) where x == -y: print("(\(x), \(y)) is on the line x == -y") case let (x, y): print("(\(x), \(y)) is just some arbitrary point") }

Kotlin

// label e break / continue loop1@ for (i in 0 until 3) { loop2@ for (j in 0 until 3) { if (i == 1 && j == 1) { continue@loop1 // pode usar break@ tb } println("i = $i, j = $j") } } // testar isso /*label: { // do stuff if (check) break label // do more stuff }*/ // switch e match (em kotlin se chama when) when (x) { 0, 1 -> print("x == 0 or x == 1") else -> print("otherwise") } when (x) { in 1..10 -> print("x is in the range") in validNumbers -> print("x is valid") !in 10..20 -> print("x is outside the range") else -> print("none of the above") }

Java

// label e break / continue loop1: for (...) { loop2: for (...) { continue loop1; // pode usar break tb } } label: { // do stuff if (check) break label; // do more stuff } // switch e "match" - java 12+ switch (day) { case MONDAY, FRIDAY, SUNDAY -> System.out.println(6); case TUESDAY -> System.out.println(7); case THURSDAY, SATURDAY -> System.out.println(8); case WEDNESDAY -> System.out.println(9); } // switch expressions - java 14+ var title = switch (person) { case Dali, Picasso -> "painter"; case Mozart, Prokofiev -> "composer"; case Goethe, Dostoevsky -> "writer"; }; // match - java 17+ switch (o) { case null -> System.out.println("null"); case String s -> System.out.println("String"); case Color c -> System.out.println("Color with " + Color.values().length + " values"); case Point p -> System.out.println("Record class: " + p.toString()); case int[] ia -> System.out.println("Array of ints of length" + ia.length); default -> System.out.println("Something else"); }

C#

// label e goto for (int a = 0; a < 10; a++) { for (int y = 0; y < 10; y++) { // Run until condition. for (int x = 0; x < 10; x++) { // Run until condition. if (x == 5 && y == 5) { goto Outer; } } dummy++; } Outer: continue; } return dummy; // switch e goto switch (id) { case 1000: price += 10; goto case 100; case 100: return price * 10; default: return price; } // switch fallthrough switch (id) { case "ab": case "cd": case "ef": // não pode haver nenhum código entre os "case" break; case "gh": break; default: // default é opcional break; } // switch e "match" - requer C# 7+ switch(shape) { case Circle c: WriteLine($"circle with radius {c.Radius}"); break; case Rectangle s when (s.Length == s.Height): WriteLine($"{s.Length} x {s.Height} square"); break; case Rectangle r: WriteLine($"{r.Length} x {r.Height} rectangle"); break; default: WriteLine("unknown shape"); break; case null: throw new ArgumentNullException(nameof(shape)); } // switch expressions - requer C# 8+ var switchValue = id switch { "ab" => 1, "cd" => 2, _ => 0 };

Dart

TypeScript

JavaScript

// label e break / continue loop1: for (i = 0; i < 3; i++) { loop2: for (j = 0; j < 3; j++) { if (i === 1 && j === 1) { continue loop1; // pode usar break tb } console.log(`i = ${i}, j = ${j}`); } } label: { // do stuff if (check) break label; // do more stuff } // switch fallthrough switch (id) { case "ab": case "cd": // algum código aqui case "ef": // não pode haver nenhum código entre os "case" break; case "gh": break; default: // default é opcional break; }

ActionScript

Python

PHP

VBA / VB6

'label e goto, resume e next On Error GoTo Erro ' Faça alguma coisa e saia da função ' antes de chegar nas linhas de tratamento de erro Exit Sub ' Label de erro ' Labels não podem conter espaços em branco antes dos nomes Erro: ' Faça alguma coisa e saia da função Exit Sub ' Ou continue a execução normalmente Resume Next ' Ou passe para um tratamento específico If Err.Number = 13 Then Resume ErroEspecifico ErroEspecifico: Exit Sub 'switch ("select") Select Case age Case 50 ageBlock = "the big five-oh" Case 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 ageBlock = "octogenarian" Case 90 To 99 ageBlock = "nonagenarian" Case Is >= 100 ageBlock = "centenarian" Case Else ageBlock = "just old" End Select

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

Assembly

Funções

Rust

// declaração de função fn normal() { /**/ } // mesmo que -> () fn normalUnit() -> () { /**/ } // expressão de função let expressao = normal; fn retorno() -> &'static str { "retorno" // sem ; no final } fn retorno() -> &'static str { return "retorno"; } use std::any::Any; fn retorno_misturado(numero:i32) -> Option<Box<dyn Any>> { if numero > 0 { return Some(Box::new("string")) } Some(Box::new(25)) } fn superior<F>(funcao:F) where F:fn() { funcao(); } fn superior<F>(funcao:F) -> &'static str where F:fn() { funcao(); } // TODO fazer superior com type aliasing superior(normal); superior(normalUnit); superior(retorno);

Go

// declaração de função func normal() { /**/ } // expressão de função var expressaoInline = func() { /**/ } var expressao = normal func retorno() string { return "retorno" } func retornoMultiplo() (string, string) { return "retorno", "multiplo" } func retornoMisturado(numero int) interface{} { if numero > 0 { return "texto" } return 25 } func retornoNomeado() (nome string) { nome = "Zé" // declarado pelo nome do retorno return nome } func superior(funcao func()) { funcao() } func superiorRetorno(funcao func() string) { funcao() } superior(normal) superiorRetorno(retorno)

C++

// declaração de função void normal() { /**/ } // expressão de função auto expressao = normal; std::string retorno() { return "retorno"; } void superior(void(*funcao)()) { funcao(); } void superior(std::string(*funcao)()) { funcao(); } // ou using Function_t = void(); void superior(Function_t* funcao) { funcao(); } using Function2_t = std::string(); void superior(Function2_t* funcao) { funcao(); } // ou using FunctionPointer = void(*)(); void superior(FunctionPointer funcao) { funcao(); } using FunctionPointer2 = std::string(*)(); void superior(FunctionPointer2 funcao) { funcao(); } // ou #include <type_traits> using FunctionPointer = std::add_pointer<void()>::type; void superior(FunctionPointer funcao) { funcao(); } using FunctionPointer2 = std::add_pointer<std::string()>::type; void superior(FunctionPointer2 funcao) { funcao(); } superior(&normal); superior(&retorno);

Objective-C

// declaração de função void normal() { /**/ } // TODO

Swift

// declaração de função func normal() { /**/ } // mesmo que -> Void ou -> () func normalVoid() -> Void { /**/ } func normalEmptyTuple() -> () { /**/ } // expressão de função let expressao = normal; func retorno() -> String { return "retorno" } func retornoMisturado(numero:Int) -> Any { if numero > 0 { return "texto"; } return 25; } func superior(funcao:() -> Void) { funcao() } func superior(funcao:() -> String) { funcao() } // TODO fazer superior com type aliasing // TODO explicar nomes de parâmetros superior(normal) superior(normalVoid) superior(normalEmptyTuple) superior(retorno)

Kotlin

fun runTransformation(f: (String, Int) -> String): String { return f("hello", 3) }

Java

-

C#

-

Dart

TypeScript

JavaScript

// declaração de função function comum() { /**/ } function normal(texto) { /**/ } // expressão de função const surpresa = function() { /**/ }; const outraSurpresa = normal; // expressão de função anônima auto executável // note os () em volta dela (function() { // })(); function retorno() { return 'retorno'; } function retornoMisturado(numero) { if (numero > 0) { return 'texto'; } return 25; } function superior(funcao) { funcao(); } // chamadas perfeitamente válidas comum(); // arguments será [] comum('lala'); // arguments será ['lala'] comum('lala', 'lolo'); // arguments será ['lala', 'lolo'] normal('lolo'); // texto será 'lolo' e arguments será ['lolo'] // chamada válida normal(); // o parâmetro texto terá o valor undefined e arguments será [] normal.call(this, 'dadaísmo'); // o parâmetro texto terá o valor 'dadaísmo' e arguments será ['dadaísmo']

ActionScript

Python

# declaração de função def normal(): pass def normal(texto): pass # expressão de função? # TODO def retorno(): return 'retorno' def retornoMisturado(numero): if (numero > 0): return 'texto' else: return 25 def superior(funcao): funcao() superior(normal) superior(retorno)

PHP

VBA / VB6

'Métodos que não retornam valores são chamados subrotinas, ou simplesmente subs Public Sub SemRetorno() '... End Sub 'Podemos sair precocemente de um sub usando Exit Sub Public Sub AbortarCedo() Dim algumaFlag As Boolean: algumaFlag = True If algumaFlag Then Exit Sub 'Equivalente à "return" End If 'Fazer o resto se passar pela flag End Sub 'Métodos com retorno são Funções Public Function ComRetorno() As Boolean 'Equivalente à "return true". 'Note que são necessárias duas linhas ComRetorno = True 'Esta atribui o valor de retorno, mas não interfere na execução das linhas seguintes Exit Function 'E esta retorna o valor especificado imediatamente End Function 'Caso o Exit Function não tenha sido usado, retorna o valor especificado quando chegar aqui 'Tanto subs quanto funções podem receber parâmetros Private Sub ComParametro(i As Byte) Exit Sub End Sub Private Function ComParametroERetorno(i As Integer) As Boolean If i <> 0 Then 'Operador diferente é <> ComParametroERetorno = True Exit Function Else ComParametroERetorno = False Exit Function End If End Function 'Ou Private Function ComParametroERetorno(i As Integer) As Boolean ComParametroERetorno = IIf(i <> 0, True, False) 'Inline If (IIf) funciona quase como operador ternário ? : Exit Function End Function 'Podemos passar vários parâmetros separando por vírgula Private Sub ComParametro(i As Long, j As Currency) '... End Sub 'E podemos quebrar os parâmetros em até 24 linhas utilizando _ (continuação de linha) 'Note que é necessário um espaço antes de _ 'E não podem haver comentários :( Private Sub ComParametro( _ i As Single, _ j As Double _ ) 'Single é float, e Double é double mesmo End Sub 'Para chamar subrotinas e funções, existem casos em que deve ser usados parênteses, e casos em que eles não devem ser usados 'O uso de parênteses quando não obrigatório faz com que os parâmetros sejam passados por valor ao invés de referência 'Teoricamente Call deveria permitir usar parênteses sempre, mas não é o caso. Não há necessidade de usar Call 'TODO Testar isso aqui Dim param As Integer: param = 1 Dim param2 As Integer: param = 1 ComRetorno Call ComRetorno retorno = ComRetorno retorno = ComRetorno() ComParametro param 'Passado por referência ComParametro(param) 'Passado por valor Call ComParametro(param) ComParametroERetorno param 'Passado por referência ComParametroERetorno(param) 'Passado por valor Call ComParametroERetorno(param) retorno = ComParametroERetorno(param) ComDoisParametros param, param2 'Passado por referência ComDoisParametros(param, param2) 'Passado por valor Call ComDoisParametros(param, param2) ComParametroERetorno param, param2 'Passado por referência ComParametroERetorno(param, param2) 'Passado por valor Call ComParametroERetorno(param, param2) retorno = ComParametroERetorno(param, param2)

Ada

Object Pascal (Delphi)

Ruby

def normal() # end alias semExpressao normal def retorno() return 'retorno' end def retornoMisturado(numero) if numero > 0 return 'texto' end return 25 end def superior yield end normal() retorno() retornoMisturado(-1) retornoMisturado(1) superior &method(:normal) superior &method(:retorno)

Smalltalk

Common Lisp

Haskell

F#

Web Assembly text format

LLVM IR

define void @normal() { ret void; }

Assembly

  1. a

A

Argumentos por referência

Rust

// ver ponteiros

Go

// ver ponteiros

C++

// ver ponteiros

Objective-C

// ver ponteiros

Swift

// tipos primitivos por valor por padrão // modificáveis com inout // arrays e objetos por referência func swapTwoInts(_ a:inout Int, _ b:inout Int) { let temp = a a = b b = temp } var a = 2 var b = 3 // requer & na frente do nome // além do inout da definição swapTwoInts(&a, &b)

Kotlin

// tipos primitivos por valor // arrays e objetos por referência

Java

// tipos primitivos por valor // arrays e objetos por referência

C#

// tipos primitivos por valor por padrão // modificáveis com ref ou out // arrays e objetos por referência public void SwapTwoInts(ref int a, ref int b) { int temp = a; a = b; b = temp; } public bool OutExample(string a, out int c) { // TODO alguma lógica condicional com a return false; } // argumentos ref precisam ser inicializados // antes de serem passados para a função var a = 2; var b = 3; SwapTwoInts(a, b); // argumentos out NÃO precisam ser inicializados // antes de serem passados para a função int c; if (!OutExample(c)) { return; }

Dart

TypeScript

JavaScript

// tipos primitivos por valor // arrays e objetos por referência

ActionScript

Python

PHP

VBA / VB6

'O padrão é passar tudo por referência, 'inclusive tipos primitivos como Ints 'Podemos forçar a passagem de um parâmetro 'por valor ou por referência usando ByVal e ByRef 'Essa palavras não tem efeito quando passamos constantes 'Arrays e User Defined Types (UDTs) não podem 'ser passados por valor Private Sub PorValor(ByVal i As Long) '... End Sub Private Sub PorReferencia(ByRef i As Long) '... End Sub

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

Argumentos opcionais

Rust

-

Go

-

C++

void point(int x, int y) { /**/ } void point(int x, int y = 4) { /**/ } void point(int x = 3, int y = 4) { /**/ }

Objective-C

-

Swift

//func point(x:Int, y:Int) { /**/ } // testar func point(x:Int, y:Int = 4) { /**/ } // func point(x:Int = 3, y:Int = 4) { /**/ } //testar

Kotlin

// fun point(x:Int, y:Int) { /**/ } // testar fun point(x:Int, y:Int = 4) { /**/ } // fun point(x:Int = 3, y:Int = 4) { /**/ } // testar // named arguments fun point(x:Int = 3, y:Int) { /**/ } // também overload como alternativa

Java

// não possui // usar overload como alternativa

C#

// public void Point(int x, int y) { /**/ } // testar public void Point(int x, int y = 4) { /**/ } // public void Point(int x = 3, int y = 4) { /**/ } // testar // também overload como alternativa

Dart

TypeScript

JavaScript

// a assinatura das funções não é verificada ao chamá-las // podemos passar mais ou menos argumentos para a função // independente de como ela foi definida // os argumentos a mais não terão nome // e os argumentos a menos terão o valor null function point(x, y) { if (y == null) { y = 4; } }

ActionScript

Python

def point(x, y = 4): #

PHP

VBA / VB6

Private Sub Point(X As Integer, Optional Y As Integer = 4) ' End Sub

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

Argumentos nomeados

Rust

// usar builder pattern // como alternativa

Go

// usar builder pattern // como alternativa

C++

// usar builder pattern // como alternativa

Objective-C

// todos os argumentos devem ser nomeados

Swift

func namedArgs( tooMany:Int, args:Int, toRemember:Bool, theirMeaning:String = "a", byPosition:String = "b" ) { // } // argumentos devem seguir a ordem // mas os que possuem valor padrão // podem ser omitidos namedArgs( tooMany: 2, args: 1, toRemember: false, byPosition: "args" ) // nomes dos argumentos que podem // ser omitidos devem usar _ para // o nome externo func unnamedArgs( tooMany:Int, _ args:Int, _ toRemember:Bool, _ theirMeaning:String = "a", _ byPosition:String = "b" ) { // } unnamedArgs(tooMany: 2, 1, false, "args")

Kotlin

fun namedArgs( tooMany:Int, args:Int, toRemember:Boolean, theirMeaning:String = "a", byPosition:String = "b" ) { // } namedArgs( tooMany = 2, args = 1, toRemember = false, byPosition = "args" ) // TODO verificar isso pq tem parâmetro faltando namedArgs( 2, args = 1, toRemember = false, byPosition = "args" ) // TODO verificar isso pq tem parâmetro faltando namedArgs(tooMany = 2, 1, false, "args")

Java

// usar builder pattern // como alternativa

C#

public class NamedArgs { public NamedArgs( int tooMany, int args, bool toRemember, string theirMeaning = "a", string byPosition = "b" ) { // } } // argumentos não precisam seguir a ordem // e os que possuem valor padrão podem // ser omitidos var ex = new NamedArgs( args: 1, toRemember: false, tooMany: 2, theirMeaning: "named", byPosition: "arg" );

Dart

TypeScript

JavaScript

// usar builder pattern // como alternativa

ActionScript

Python

def named_args(tooMany, args, toRemember, theirMeaning = 'a', byPosition = 'b'): # # TODO mais testes named_args(tooMany = 2, args = 1, toRemember = false)

PHP

VBA / VB6

'usar builder pattern 'como alternativa

Ada

Object Pascal (Delphi)

Ruby

def named_args( tooMany:, args:, toRemember:, theirMeaning: 'a', byPosition: 'b' ) # end named_args( tooMany: 2, args: 1, toRemember: false )

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

Sobrecarga de função

Rust

Go

-

C++

Objective-C

-

Swift

-

Kotlin

Java

C#

Dart

TypeScript

JavaScript

-

ActionScript

Python

PHP

VBA / VB6

-

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

Funções e Métodos Variádicos

Rust

// argumentos do mesmo tipo // usa macros para argumentos variádicos O_O' macro_rules! imprimirSimples { ($titulo:expr, $($pagina:expr), +) => {{ // na "assinatura" do macro não dá pra diferenciar os tipos // mas o corpo vai lançar exceção na linha quando compilar // se o tipo não for &str let titulo:&str = $titulo; $( // poderíamos fazer a verificação dos tipos aqui tb // se necessário let pagina = $pagina; println!("Imprimindo página {}", pagina); )+ }}; } imprimirSimples!("resumo", 1, 2, 5);

Rust

// argumentos de todos os tipos // TODO

Go

// argumentos do mesmo tipo func imprimirSimples(titulo string, paginas ...int) { for _, pagina := range paginas { fmt.Printf("Imprimindo página %v)\n", pagina) } } imprimirSimples("resumo", 1, 2, 5)

Go

// argumentos de todos os tipos func imprimir(titulo string, paginas ...interface{}) { for _, pagina := range paginas { switch value := pagina.(type) { case string: fmt.Println("A string") fmt.Println("Imprimindo página ", value) case int32: fmt.Println("An integer") fmt.Println("Imprimindo página ", value) case []int32: fmt.Println("A slice") fmt.Println("Imprimindo páginas ", value) default: fmt.Println("A default") } } } pageSlice := make([]int32, 3) imprimir("resumo", 1, pageSlice, "capítulo 2")

C++

// argumentos do mesmo tipo #include <iostream> using std::string; using std::cout; using std::endl; template<typename... Tipos> void imprimirSimples(string titulo, Tipos... paginas) { const uint16_t quantidadeDeParametros {sizeof...(paginas)}; // não pode criar uma array com 0 elementos if (quantidadeDeParametros == 0) { return; } // expande os argumentos int paginasArray[quantidadeDeParametros] {paginas...}; for (auto pagina : paginasArray) { cout << "Imprimindo página " << pagina << endl; } } imprimirSimples("resumo", 1, 2, 5);

C++

// argumentos de todos os tipos #include <iostream> #include <boost/range/irange.hpp> using std::string; using std::cout; using std::endl; /// imprimirHelper template genérico template<typename T> void imprimirHelper(T pagina) { // poderia usar a linha abaixo para descobrir o tipo de T // porém, melhor usar o template especializado // if (std::is_same<T, int>::value) { /* ... */ } cout << "Imprimindo outra coisa" << endl; } /// imprimirHelper template especializado para int template<> void imprimirHelper<int>(int pagina) { cout << "Imprimindo página " << pagina << endl; } /// imprimirHelper template especializado para boost::irange template<> void imprimirHelper<boost::irange>(boost::irange faixa) { cout << "Imprimindo página " << std::begin(faixa) << " até " << std::end(faixa) << endl; } // foward declaration imprimir template?? Não estou certo da função disso :/ void imprimir(string titulo) {} // implementação imprimir template template<typename Tipo, typename... Tipos> void imprimir(string titulo, Tipo pagina, Tipos... paginas) { // executa o helper especializado e chama recursivamente a si mesmo imprimirHelper(pagina); imprimir(titulo, paginas...); } imprimir<int, boost::irange, string>("resumo", 1, boost::irange(2, 5), "capítulo 2");

Objective-C

// macros não seguras estilo C #include <iostream> #include <cstdarg> void imprimirSimplesMacro(const std::string titulo, ...) { // va_list argumentos recebe o que vir depois do parâmetro titulo va_list argumentos; va_start(argumentos, titulo); int pagina; while (true) { pagina = va_arg(argumentos, int); if (pagina == -1) { break; } std::cout << "Imprimindo " << pagina << std::endl; } va_end(argumentos); } // preciso sempre passar -1 no final como terminador // se não dá overflow e lê pedaço de memória além do que deveria imprimirSimplesMacro("resumo", 1, 2, 5, -1);

Swift

// argumentos do mesmo tipo func imprimirSimples(titulo titulo:String, paginas:Int...) { for pagina in paginas { print("Imprimindo página \(pagina) num total de \(paginas.count)") } } imprimirSimples(titulo: "resumo", paginas: 1, 2, 5)

Swift

// argumentos de todos os tipos func imprimir(titulo titulo:String, paginas:Any...) { for valor in paginas { switch valor { case let pagina as Int: print("Imprimindo página \(pagina)") case let faixa as Range<Int>: print("Imprimindo páginas \(faixa.first!) até \(faixa.last!)") default: print("Imprimindo outra coisa") } } } imprimir(titulo: "resumo", paginas: 1, 2...5, "capítulo 2")

Kotlin

// argumentos do mesmo tipo imprimirSimples(titulo:String, vararg paginas:Int) { /*for (int pagina : paginas) { System.out.println(String.format("Imprimindo página %1", pagina)); }*/ } imprimirSimples("resumo", 1, 2, 5);

Kotlin

// argumentos de todos os tipos /*void imprimir(titulo:String, Object... paginas) { for (Object valor : paginas) { if (valor instanceof Integer) { System.out.println(String.format("Imprimindo página %d", valor)); } else if (valor instanceof Range<Integer>) { System.out.println(String.format( "Imprimindo páginas %d até %d", ((Range<Integer>)valor).getMinimum(), ((Range<Integer>)valor).getMaximum() )); } else { System.out.println("Imprimindo outra coisa"); } } } imprimir("resumo", 1, Range.between(2, 5), "capítulo 2");*/

Java

// argumentos do mesmo tipo void imprimirSimples(String titulo, int... paginas) { for (int pagina : paginas) { System.out.println(String.format("Imprimindo página %1", pagina)); } } imprimirSimples("resumo", 1, 2, 5);

Java

// argumentos de todos os tipos void imprimir(String titulo, Object... paginas) { for (Object valor : paginas) { if (valor instanceof Integer) { System.out.println(String.format("Imprimindo página %d", valor)); } else if (valor instanceof Range<Integer>) { System.out.println(String.format( "Imprimindo páginas %d até %d", ((Range<Integer>)valor).getMinimum(), ((Range<Integer>)valor).getMaximum() )); } else { System.out.println("Imprimindo outra coisa"); } } } imprimir("resumo", 1, Range.between(2, 5), "capítulo 2");

C#

// argumentos do mesmo tipo void ImprimirSimples(string titulo, params int[] paginas) { foreach (int pagina in paginas) { System.Console.WriteLine( @"Imprimindo pagina {0} num total de {1}", pagina, paginas.Length ); } } ImprimirSimples(@"resumo", 1, 2, 5);

C#

// argumentos de todos os tipos void Imprimir(string titulo, params object[] paginas) { foreach (object valor in paginas) { if (valor is int) { System.Console.WriteLine(@"Imprimindo página {0}", valor); } else if (valor is IEnumerable<int>) { System.Console.WriteLine( @"Imprimindo páginas {0} até {1}", (valor as IEnumerable<int>).First(), (valor as IEnumerable<int>).Last() ); } else { System.Console.WriteLine(@"Imprimindo outra coisa"); } } } Imprimir(@"resumo", 1, Enumerable.Range(2, 4), @"capítulo 2");

Dart

TypeScript

JavaScript

'use strict'; // argumentos do mesmo tipo function imprimirSimples(titulo, ...paginas) { for (let pagina of paginas) { console.log(`Imprimindo página ${pagina}`); } } imprimirSimples("resumo", 1, 2, 5);

JavaScript

'use strict'; // argumentos de todos os tipos function imprimir(titulo, ...paginas) { for (let valor of paginas) { if (Number.isInteger(valor)) { console.log(`Imprimindo página ${valor}`); } else if ((valor.begin || valor.begin === 0) && valor.end ) { console.log(`Imprimindo páginas ${valor.begin} até ${valor.end}`); } else { console.log('Imprimindo outra coisa'); } } } imprimir("resumo", 1, {begin: 2, end: 5}, "capítulo 2");

ActionScript

Python

# argumentos do mesmo tipo def imprimirSimples(titulo, *paginas): for pagina in paginas: print("Imprimindo página " + pagina) imprimirSimples()

Python

# argumentos de todos os tipos def imprimir(titulo, *paginas): for valor in paginas: # TODO imprimir()

PHP

VBA / VB6

' argumentos do mesmo tipo Public Sub ImprimirSimples(titulo As String, ParamArray paginas() As Integer) Dim pagina As Integer For Each pagina In paginas Print pagina Next End Sub Imprimir "resumo", 1, 2, 5

Ada

Object Pascal (Delphi)

Ruby

# argumentos do mesmo tipo def imprimirSimples(titulo, *paginas) for pagina in paginas puts "Imprimindo página #{pagina}" end end imprimirSimples("resumo", 1, 2, 5);

Ruby

# argumentos de todos os tipos def imprimir(titulo, *paginas) for valor in paginas if valor.is_a? Numeric puts "Imprimindo página #{valor}" elsif (defined?(valor.begin) || (defined?(valor.begin) && valor.begin === 0)) && defined?(valor.end) puts "Imprimindo páginas #{valor.begin} até #{valor.end}" else puts "Imprimindo outra coisa" end end end imprimir("resumo", 1, 2..5, "capítulo 2")

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

  1. a

A

Lambdas

Rust

fn main() { // Increment via closures and functions. fn function(i:i32) -> i32 { i + 1 } // Closures are anonymous, here we are binding them to references // Annotation is identical to function annotation but is optional // as are the `{}` wrapping the body. These nameless functions // are assigned to appropriately named variables. let closure_annotated = |i:i32| -> i32 { i + 1 }; let closure_inferred = |i | i + 1 ; let i = 1; // Call the function and closures. println!("function: {}", function(i)); println!("closure_annotated: {}", closure_annotated(i)); println!("closure_inferred: {}", closure_inferred(i)); // A closure taking no arguments which returns an `i32`. // The return type is inferred. let one = || 1; println!("closure returning one: {}", one()); }

Go

// suporta funções anônimas e closures // mas não lambda com arrow syntax ou algo parecido func superiorRetorno(funcao func(x int) int) { fmt.Println(funcao(1)) } superiorRetorno(func(x) { return x + 1 })

C++

Objective-C

Swift

func superior(funcao:() -> Void) { funcao() } // declaração simplificada superior({() in print("lambda")}) func superior(funcao:(_:Int) -> Int) { print(funcao(1)) } // declaração simplificada superior({x in x + 1}) // declaração completa superior({(x:Int) -> Int in return x + 1 }) // superior({x, y in x + y})

Kotlin

val sum:(Int, Int) -> Int = { x:Int, y:Int -> x + y } // suporta closures tb

Java

public class Main { public static void main(String[] args) { // não são funções de verdade, são classes // que podem ser declaradas como se fossem // funções lambda, mas ainda é preciso chamar // o método da classe para executá-las // no caso do exemplo, o método se chama call // declaração simplificada Main.superior(() -> System.out.println("lambda")); // declaração simplificada Main.superior(x -> x + 1); // declaração completa Main.superior((int x) -> { return x + 1; }); // Main.superior(x, y -> x + y); } @FunctionalInterface public interface Lambda { void call(); } public static void superior(Lambda funcao) { funcao.call(); } @FunctionalInterface public interface Lambda2 { int call(int x); } public static void superior(Lambda2 funcao) { System.out.println(funcao.call(1)); } }

C#

public class Main { public static void Main(string[] args) { // declaração simplificada Main.superior(() => System.Console.WriteLine("lambda")); // declaração simplificada Main.superior(x => x + 1); // declaração completa Main.superior((int x) => { return x + 1; }); // Main.superior(x, y -> x + y); } public delegate void LambdaDelegate(); public static void superior(LambdaDelegate funcao) { funcao(); } public delegate int Lambda2Delegate(int x); public static void superior(Lambda2Delegate funcao) { System.Console.WriteLine(funcao(1)); } }

Dart

TypeScript

JavaScript

function superior(funcao) { funcao(); } // declaração simplificada superior(() => console.log('lambda')); // declaração antiga superior(function() { /**/ }); function superior2(funcao) { console.log(funcao(1)); } // declaração simplificada superior(x => x + 1); // declaração completa superior((x) => { return x + 1; }); // superior(x, y => x + y)

ActionScript

Python

x = lambda a, b, c : a + b + c # TODO mover para exemplo de closure def myfunc(n): return lambda a : a * n mydoubler = myfunc(2)

PHP

VBA / VB6

' ver exemplo

Ada

Object Pascal (Delphi)

Ruby

def adder(a, b) lambda { a + b } end adder_fn = adder(1, 2) adder_fn.call

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

  1. a

A

Funções Internas

Rust

fn externa() { fn interna() { /**/ } // let internaLambda = || { /**/ }; interna(); internaLambda(); }

Go

func externa() { func main() { internaLambda := func() { /**/ } internaLambda() } }

C++

void externa() { auto internaLambda = [](){ /**/ }; // ou struct internaFunctor { // testar isso void operator()() { /**/ } }; internaLambda(); internaFunctor(); }

Objective-C

// blocks em métodos

Swift

func externa() { func interna() { /**/ } // let internaLambda = {() in /**/ } interna() internaLambda(); }

Kotlin

Java

public class Main { public static void main(String[] args) { // não são funções de verdade // ver lambdas acima para explicação Funcional interna = () -> { System.out.println("interna"); }; interna.call(); Funcional2 interna2 = x -> x + 1; int y = interna2.call(1); } @FunctionalInterface public interface Funcional { void call(); } @FunctionalInterface public interface Funcional2 { int call(int x); } }

C#

public class Main { public static void Main(string[] args) { InternaDelegate interna = () => { System.Console.WriteLine(@"interna"); }; interna(); Interna2Delegate interna2 = x => x + 1; var y = interna2(1); // ou Action interna = new Action(() => { System.Console.WriteLine(@"interna"); })); // testar isso Func<int> interna2 = new Func<int>(x => x + 1); // C# 7 deverá permitir funções locais também } delegate void InternaDelegate(); delegate int Interna2Delegate(int x); }

Dart

TypeScript

JavaScript

function externa() { function interna() { /**/ } let internaLambda = () => { /**/ }; interna(); internaLambda(); }

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

  1. Swift / Rust / JavaScript
  2. C++
  3. C#
  4. Java
  5. Objective-C

Swift, Rust e JavaScript permitem a criacão natural de funções dentro de funções.
C++ requer o uso de um lambda, mas seu tipo pode ser deduzido pelo compilador.
C# também usa um lambda, mas seu tipo deve ser declarado por meio de um delegate.
Java não possui funções internas de verdade. São classes com uma sintaxe um pouco mais reduzida.
Objective-C?

Closures

Rust

Go

package main import "fmt" func facade() func() int { // acessível somente pela função interna i := 0 interna := func() int { i++ return i } // expõe a função interna return interna } func main() { closure := facade() fmt.Println(closure()) // 1 fmt.Println(closure()) // 2 }

C++

#include <iostream> int main(int argc, const char* argv[]) { using std::make_shared; using std::cout; using std::endl; auto facade = [](){ // acessível somente pela função interna auto i = make_shared<int>(); auto interna = [i](){ (*i)++; return *i; }; // expõe a função interna return interna; }; auto closure = facade(); cout << closure() << endl; // 1 cout << closure() << endl; // 2 return 0; }

Objective-C

#import <Foundation/Foundation.h> int main(int argc, const char* argv[]) { // typedef ajuda na legibilidade typedef int (^interna_t)(void); typedef interna_t (^facade_t)(void); facade_t facade = ^{ // acessível somente pela função interna __block int i = 0; interna_t interna = ^{ i++; return i; }; // expõe a função interna return interna; }; interna_t closure = facade(); NSLog(@"%i", closure()); // 1 NSLog(@"%i", closure()); // 2 return 0; }

Swift

func facade() -> () -> Int { // acessível somente pela função interna var i = 0 func interna() -> Int { i = i + 1 return i } // expõe a função interna return interna } let closure = facade(); print(closure()); // 1 print(closure()); // 2

Kotlin

Java

class ClosureState { public int i; } public class MainClosure { @FunctionalInterface public interface Interna { int call(); } static Interna facade() { // acessível somente pela "função" interna final ClosureState closureState = new ClosureState(); Interna interna = () -> { closureState.i++; return closureState.i; }; // expõe a "função" interna return interna; } public static void main(String[] args) { Interna closure = facade(); System.out.println(closure.call()); // 1 System.out.println(closure.call()); // 2 } } // PS: pra evitar ter que declarar uma classe ClosureState // eu poderia ter feito final Object closureState = new Object() { public int i; }; // mas aí para ler as propriedades eu teria que usar // reflection toda a vez Class ClosureClass = closureState.getClass(); Field IField = ClosureClass.getDeclaredField("i") IField.getInteger(closureState);

C#

public class MainClassClosure { delegate int InternaDelegate(); static InternaDelegate Facade() { // acessível somente pela função interna int i = 0; InternaDelegate interna = () => { i++; return i; }; // expõe a função interna return interna; } public static void Main(string[] args) { var closure = Facade(); System.Console.WriteLine(closure()); // 1 System.Console.WriteLine(closure()); // 2 } }

Dart

TypeScript

JavaScript

'use strict'; function facade() { // acessível somente pela função interna let i = 0; let interna = () => { i++; return i; }; // expõe a função interna return interna; } let closure = facade(); console.log(closure()); // 1 console.log(closure()); // 2

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

  1. Swift / JavaScript
  2. Rust?
  3. C#
  4. C++
  5. Java
  6. Objective-C

Swift e JavaScript são os mais sucintos. É verdade que é necessário saber da existência de closures para não criar uma sem querer, como muitos programadores JavaScript devem ter descoberto da pior maneira. Porém as novas regras de escopo, similares às das demais linguagens minimizam esse problema.
Rust?
Em comparação com as linguagens anteriores, C# requer apenas a declaração de um delegate a mais.
C++ por sua vez, requer cuidados no gerenciamento de memória das variáveis acessadas pela closure com make_shared.
Java complica um pouco o padrão, requerendo que as variáveis sejam membros de um objeto marcado como final.
Objective-C possui uma sintaxe bastante difícil para identificar as closures, e o uso de aliases torna as assinaturas um pouco mais legíveis. Também é necessário identificar de maneira especial as variáveis que serão usadas na closure com __block.

Assinatura e strategy pattern

Rust

type StrategySignature = fn(i32, i32) -> i32 //

Go

type StrategySignature func(int, int) int func AddStrategy(i1 int, i2 int) int { return i1 + i2 } func MultiplyStrategy(i1 int, i2 int) int { return i1 * i2 } func main() { var typeCurrentStrategy StrategySignature var inlineCurrentStrategy func(int, int) int typeCurrentStrategy = AddStrategy inlineCurrentStrategy = AddStrategy typeCurrentStrategy(1, 2) // 3 typeCurrentStrategy(1, 2) // 3 typeCurrentStrategy = MultiplyStrategy inlineCurrentStrategy = typeCurrentStrategy typeCurrentStrategy(1, 2) // 2 typeCurrentStrategy(1, 2) // 2 }

C++

Objective-C

Swift

typealias StrategySignature = (Int, Int) -> Int func addStrategy(_ i1:Int, _ i2:Int) -> Int { return i1 + i2 } func multiplyStrategy(_ i1:Int, _ i2:Int) -> Int { i1 * i2 } var subtractStrategy = {(i1:Int, i2:Int) -> Int in i1 - i2 } var divideStrategy:StrategySignature = { i1, i2 in i1 / i2 } var otherStrategy:StrategySignature = {$0 + $1} var typeCurrentStrategy:StrategySignature var inlineCurrentStrategy:func(Int, Int) -> Int typeCurrentStrategy = addStrategy inlineCurrentStrategy = addStrategy typeCurrentStrategy(1, 2) // 3 typeCurrentStrategy(1, 2) // 3 typeCurrentStrategy = multiplyStrategy inlineCurrentStrategy = typeCurrentStrategy typeCurrentStrategy(1, 2) // 2 typeCurrentStrategy(1, 2) // 2

Kotlin

// notice that for signatures // the return type is separated by -> and not : // ugh... typealias StrategySignature = (Int, Int) -> Int fun addStrategy(i1:Int, i2:Int) :Int { return i1 + i2 } val multiplyStrategy = fun(i1:Int, i2:Int) :Int { i1 * i2 } val subtractStrategy:StrategySignature = { i1, i2 -> i1 - i2 } //

Java

C#

delegate int StrategySignature(int, int); //

Dart

TypeScript

JavaScript

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

  1. a

A

Módulos

Rust

mod

Rust

use

Go - moduleRootFolder

# dentro de um diretório go mod init github.com/path/to/module/repo # isso vai criar um go.mod

Go - moduleRootFolder/go.mod

module github.com/path/to/module/repo go 1.15

Go - moduleRootFolder/subfolder/sub.go

package subfolder // nome do pacote não precisa ser // o mesmo da pasta, mas é recomendado func init() { // executado quando um pacote é importado } // nomes começando com maiúsculo // são visíveis fora do pacote func ExportedFunc() { // } type ExportedStruct struct { // } // nomes começando com minúsculo // só são visíveis dentro do próprio pacote func packagePrivate() { // }

Go - moduleRootFolder/othersubfolder/main.go

package main // import with . in front will remove the need to use // the full package.struct name, only struct name would do // import with _ in front for using side-effects only // (running the init func) // use o caminho configurado em go.mod + nome do pacote import ( "github.com/path/to/module/repo/subfolder" ) // ExportedStruct alias without namespace type ExportedStruct = sub.ExportedStruct func main() { // use o alias criado exportedStruct := ExportedStruct{} // ou o nome completo exportedStruct := sub.ExportedStruct{} sub.ExportedFunc() }

C++ 20+ - modulo.cpp

export module marcoluglio; export class DentroDoModulo; class DentroDoModulo final { // ... };

C++ 20+ - main.cpp

import marcoluglio; int main() { auto meuObjeto = DentroDoModulo(); }

C++ - DentroDoModulo.hpp

#ifndef MARCOLUGLIO_DENTRODOMODULO_HPP_INCLUDED #define MARCOLUGLIO_DENTRODOMODULO_HPP_INCLUDED namespace marcoluglio { class DentroDoModulo {}; } #endif /* MARCOLUGLIO_DENTRODOMODULO_HPP_INCLUDED */

C++ - DentroDoModulo.cpp

#include "DentroDoModulo.hpp" namespace marcoluglio { // }

C++ - main.cpp

#include "DentroDoModulo.hpp" int main(int argc, const char* argv[]) { using marcoluglio::DentroDoModulo; DentroDoModulo meuObjeto = DentroDoModulo(); }

Objective-C - MLGDentroDoModulo.h

#import <Foundation/Foundation.h> @interface MLGDentroDoModulo : NSObject // @end

Objective-C - MLGDentroDoModulo.m

#import "MLGDentroDoModulo.h" @implementation MLGDentroDoModulo // @end

Objective-C - main.m

#import <Foundation/Foundation.h> #import "MLGDentroDoModulo.h" int main(int argc, const char* argv[]) { MLGDentroDoModulo* meuObjeto; meuObjeto = [[MLGDentroDoModulo alloc] init]; return 0; // não possui namespaces // a utilização de prefixos com 3 letras // ou mais nas classes é a alternativa // recomendada }

Swift - DentroDoModulo.swift

// a criação de namespaces é implícita // para cada módulo // um módulo é um agrupamento macro, bem // diferente do que se utiliza nas // outras linguagens // ele abrange um target inteiro de // compilação como um framework, // uma biblioteca ou um executável import UIKit class DentroDoModulo : UIViewController { }

Swift - main.swift

let meuObjeto = DentroDoModulo()

Kotlin

Java - marcoluglio/DentroDoModulo.java

package marcoluglio; public class DentroDoModulo { /**/ }

Java - main.java

import marcoluglio.DentroDoModulo; public class OlaMundo { public static void main(String[] args) { DentroDoModulo meuObjeto; meuObjeto = new DentroDoModulo(); } }

C# - DentroDoModulo.cs

namespace marcoluglio { public class DentroDoModulo { /**/ } }

C# - main.cs

using marcoluglio; class MainClass { public static void Main(string[] args) { DentroDoModulo meuObjeto; meuObjeto = new DentroDoModulo(); } }

Dart

TypeScript

JavaScript - DentroDoModulo.js

'use strict'; export default class DentroDoModulo { /**/ }

JavaScript - main.js

'use strict'; import DentroDoModulo from 'DentroDoModulo'; let meuObjeto = new DentroDoModulo();

JavaScript compatibilidade

'use strict'; // AMD define('dentroDoModulo', () => { const DentroDoModulo = class DentroDoModulo() { /**/ } return DentroDoModulo; }); define(['dentroDoModulo'], (DentroDoModulo) => { let meuObjeto = new DentroDoModulo(); }); // CommonJS // TODO

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

  1. C# / Java
  2. JavaScript
  3. Rust
  4. C++
  5. Swift
  6. Objective-C

C# e Java possuem maior granularidade. A única diferença entre os dois é que o módulo em Java deve ser replicado na estrutura de pastas dos arquivos que contém as classes, ao passo que em C# não. Se você já teve que cavar dentro de mil pastas por classes Java sabe que isso acaba mais atrapalhando do que ajudando. Porém, deve haver certamente quem diga que a liberdade que C# proporciona nesse quesito pode ser mal utilizada e gerar confusão.
JavaScript até a versão ES6, não possuía nenhuma sintaxe especial para definir módulos. Mesmo após a oficialização da especificação, nenhum navegador a implementou até o momento. O que vemos no exemplo é um padrão denominado AMD que é bastante flexível, porém um pouco redundante e propenso a erros.
Rust?
C++ possui passos manuais na definição de módulos. A sintaxe para aninhar namespaces só será melhorada na próxima especificação (c++1z). Oficialmente a forma de garantir que um módulo não seja importado mais de uma vez, e por consequência sobrescrito, é usar os include guards #ifndef, #define e #endif. A diretiva mais amigável #pragma once não é oficial, embora a maioria dos compiladores reconheça devido à sua popularidade.
Swift tem uma definição tão abrangente de módulos que quase não se pode dizer que ele tenha uma.
Objective-C herda de C?

Visibilidade

Rust

// se não especificar é private // pub para tornar padrão

Go

/* In Go, an identifier that starts with a capital letter is exported from the package, and can be accessed by anyone outside the package that declares it. If an identifier starts with a lower case letter, it can only be accessed from within the package. If you need members in a type to only be accessed by members of that type, you then need to place that type and its member functions in a separate package, as the only type in that package. */

C++

// padrão é?? // public protected private

Objective-C

Swift

/* padrão é internal public class SomePublicClass {} internal class SomeInternalClass {} fileprivate class SomeFilePrivateClass {} private class SomePrivateClass {} extensions podem acessar private */

Kotlin

/* public é padrão private, protected, internal and public tem traits? podem acessar private? */

Java

// padrão é package private // que subclasses não conseguem acessar // public protected private para modificar

C#

/* public Access is not restricted. protected Access is limited to the containing class or types derived from the containing class. internal Access is limited to the current assembly. protected internal Access is limited to the current assembly or types derived from the containing class. private Access is limited to the containing type. private protected Access is limited to the containing class or types derived from the containing class within the current assembly. Available since C# 7.2. extension methods podem acessar private? */

Dart

TypeScript

JavaScript

// export import // dentro de um módulo tudo é public // pode documentar com JSDoc // a visibilidade sugerida // usar _ como sugestão // ou closures

ActionScript

Python

# começando com _ é protected # começando com __ é private

PHP

VBA / VB6

'ver descrição 'Private A classe não pode ser acessada fora do projeto. 'Public Not Creatable Instâncias da classe somente podem ser criadas dentro do projeto que definiu a classe.Outras aplicações , no entanto, podem acessar a classe. 'SingleUse Outras aplicações podem criar instâncias da classe.Porém a cada instância criada inicia uma cópia do programa que contém a classe. 'Global SingleUse A classe atua como uma variável goblal no programa cliente. 'MultiUse Outras aplicações podem criar inúmeras instâncias da classe iniciando somente uma vez o programa que contém a classe. Os projetos ActiveX DLL comportam-se assim. 'Global MultiUse Idêntica a MultiUse mas a classe atua como uma variável goblal no programa cliente.

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

  1. a

A

Exceções

Rust

// retornar múltiplos valores com Result<R, E> fn may_return_error(x:i32) -> Result<i32, &'static str> { None => Err("Error"), // retorna um erro Some(0) => Err("0 não permitido"), // retorna um erro Some(_) => Ok(x), } match may_return_error(1) { Ok(result) => println!("{}", result), Err(err) => println!("Error: {}", err), } // runtime panic + match Ok, Err fn may_runtime_panic() -> &str { panic!("Error message"); // gera uma exceção "Ok" } match may_runtime_panic() { Ok(result) => println!("{}", result), Err(err) => println!("Error: {}", err), } // ou // pode usar Result ou Option fn a() -> Result<a, b> { // TODO let result = may_runtime_panic()?; Ok(result) } // try {} block e ? // acompanhe essa feature // e unstable docs // NÃO COPIE!!! DEPRECATED!!! // houve uma proposta de usar do catch {}, // mas ela foi substituída pelo try {} // havia uma sintaxe para try! // mas ela foi substituída por ? let result = try!(may_panic()); // 2015- let result = r#try!(may_panic()); // 2018 legacy

Go

// retornar múltiplos valores func mayReturnError(fileName string) (content string, err error) { // defer é mais ou menos um bloco "finally" // sempre vai executar ao final da função // em que foi definido // se você tiver vários defers eles irão // executar na ordem oposta em que foram // definidos (first in, last out) file, err := os.Open(fileName) defer file.Close() if err != nil { return "", err // retorna um erro } return file.String(), err } // runtime panic + recover func mayRuntimePanic() { panic("Error message") // gera uma exceção } func f() { // bloco "catch" como um lambda auto executável // o que torna ele um catch ao invés de um finally // é que nós checamos o resultado de recover antes // de prosseguir defer func() { // recover() == nil se nenhum panic ocorreu if r := recover(); r == nil { return } fmt.Println("Recovered control") }() mayRuntimePanic() }

C++

#include <exception> using std::exception; try { throw anyType; // gera uma exceção // ou simplesmente throw; // gera uma exceção } catch (const exception& ex) { // roda se jogou uma exceção } catch (...) { // roda sempre, independente se uma exceção ocorreu ou não } // NÃO COPIE!!! DEPRECATED!!! // havia uma sintaxe para "checked exceptions" int podeOuNao(int param) throw(); int podeOuNao(int param) throw(someType);

Objective-C

- (void) someMethod { @try { @throw exception; // gera uma exceção } @catch (NSException *exception) { // roda se jogou uma exceção } @finally { // roda sempre, independente se uma exceção ocorreu ou não } } // ou someCFunction(); // TODO exception estilo C, com error codes?

Swift

enum MLError : Error { case Bad case Worse case Worst } // throws antes do corpo da função indica // que ela pode gerar uma exceção e // vai propagá-la ao invés de tratá-la // cabe a quem executou a função tratar // a exceção OBRIGATORIAMENTE // ou indicar que vai propagá-la também func podeOuNao() throws -> String { throw MLError.Bad } // para outras funções, é esperado que // a exceção seja tratada dentro dela mesma func naoPode() -> String { // } // para tratar exceções // defer é mais ou menos um bloco "finally" // sempre vai executar ao final da função // em que foi definido // se você tiver vários defers eles irão // executar na ordem oposta em que foram // definidos (first in, last out) do { // abrir resources defer { // fechar resources } try throw MLError.Bad // gera uma exceção } catch MLError.Bad { // roda se jogou uma exceção } catch MLError.Worse, MLError.Worst { // roda se jogou uma exceção } // ou com try? - nil se jogar exceção let result = try? podeOuNao() { // roda se for tudo bem } // mesmo que let result = try? podeOuNao() guard result != nil else { return } // ou com try! - gera runtime exception se throws let result = try! podeOuNao() // TODO rethrows

Kotlin

Java - Main.java

public class Main { // throws antes do corpo da função indica // que ela pode gerar uma exceção e // vai propagá-la ao invés de tratá-la // cabe a quem executou a função tratar // a exceção OBRIGATORIAMENTE // ou indicar que vai propagá-la também public static void main(String[] args) throws Exception { throw new Exception(); } }

Java - Main.java

public class Main { // para outras funções, é esperado que // a exceção seja tratada dentro dela mesma public static void main(String[] args) { PodeOuNao problematico = new PodeOuNao(); // para tratar exceções // obrigatório tratar ou indicar que vai propagar try { problematico.checkedMethod(); } catch (Exception ex) { // roda se jogou uma exceção } finally { // roda sempre } problematico.uncheckedMethod(); } }

Java - Main.java

public class Main { public static void main(String[] args) { PodeOuNao problematico = new PodeOuNao(); // para tratar exceções // opcional tratar ou indicar que vai propagar try { problematico.uncheckedMethod(); } catch (Exception ex) { // roda se jogou uma exceção } finally { // roda sempre } } }

Java - PodeOuNao.java

package marcoluglio.exceptionexample; public final class PodeOuNao { // checked exceptions devem ser cercadas por // try catch ou o método deve indicar explicitamente // que pode lançá-las com "throws" public void checkedMethod() throws Exception { throw new Exception("pego na compilação!"); } // unchecked exceptions não precisam de tais // cuidados public void uncheckedMethod() { throw new RuntimeException("pego na execução!"); } }

C#

try { throw new ArgumentException("Error"); // gera uma exceção } catch (Exception ex) { // roda se jogou uma exceção } finally { // roda sempre } try { // sem finally } catch { // roda se jogou uma exceção } try { // sem catch } finally { // roda sempre }

Dart

TypeScript

JavaScript

try { throw anyType; // gera uma exceção // mas geralmente throw new Error('Whoops!'); // gera uma exceção } catch (e if e instanceof Error) { // roda se jogou uma exceção } catch (ex) { // roda se jogou uma exceção } finally { // roda sempre } try { // sem catch } finally { // }

ActionScript

Python

try: raise Exception("Error") # gera uma exceção # ou simplesmente raise # gera uma exceção except Exception as ex: # roda se jogou uma exceção finally: # roda sempre try: # sem finally except: # roda se jogou uma exceção try: # sem except finally: # roda sempre

PHP

VBA / VB6

Private Sub CapturaDeErro() ' Visual Basic não possui try catch ' Usamos labels para tratar erros On Error GoTo Erro ' Faça alguma coisa e saia da função ' antes de chegar nas linhas de tratamento de erro Exit Sub ' Label de erro ' Labels não podem conter espaços em branco antes dos nomes Erro: ' Faça alguma coisa e saia da função Exit Sub ' Ou continue a execução normalmente Resume Next ' Ou passe para um tratamento específico If Err.Number = 13 Then Resume ErroEspecifico ErroEspecifico: Exit Sub End Sub

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

  1. a

A

Async / Execução em paralelo

Generators

Yield

Go

-

C++

#include <coroutine> generator<int> iota(int n = 0) { while(true) { co_yield n++; } }

Objective-C

-

Swift

-

Kotlin

-

Java

-

C# - AnimadorGenerator.cs

using System.Collections.Generic; namespace MarcoLuglio.ClosureGeneratorExample { public class AnimadorGenerator { // os parâmetros não podem ser ref nem out public IEnumerable<float> Animar(float inicio, float fim, int tempo) { var tempoAtual = 1; var delta = (fim - inicio) / tempo; var passo = 0f; while (tempoAtual <= tempo) { try { passo = fim - (delta * (tempo - tempoAtual)); tempoAtual += 1; yield return passo; } finally { // não posso usar catch com generators } } // também posso usar yield break; se quiser interromper } } }

C# - MainClass.cs

using System; namespace MarcoLuglio.ClosureGeneratorExample { public class MainClass { public static void Main(string[] args) { var animadorGenerator = new AnimadorGenerator(); var animadorIterator = animadorGenerator.Animar(0, 100, 9); foreach (var resultado in animadorIterator) { Console.WriteLine(resultado); } // ou var animadorIterator = animadorGenerator.Animar(0, 100, 9).GetEnumerator(); while (animadorIterator.MoveNext()) { var resultado = animadorIterator.Current; Console.WriteLine(resultado); } } } }

Dart

TypeScript

JavaScript - animar.js

'use strict'; function* animar(inicio, fim, tempo) { var tempoAtual = 1; var delta = (fim - inicio) / tempo; var passo = 0f; while (tempoAtual <= tempo) { try { passo = fim - (delta * (tempo - tempoAtual)); tempoAtual += 1; yield passo; } catch (ex) { // } } }

JavaScript - main.js

'use strict'; let animadorIterador = animar(0, 100, 9); for (let resultado of animadorIterator) { console.log(resultado.value); } // ou do { let resultado = animadorIterador.next(); if (resultado.value || resultado.value === 0) { console.log(resultado.value); } } while (!resultado.done)

ActionScript

Python

def firstn(n): num = 0 while num < n: yield num num += 1

PHP

VBA / VB6

-

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Closures

Rust

Go

package main import "fmt" func intSeq() func() int { i := 0 return func() int { i++ return i } } func main() { nextInt := intSeq() fmt.Println(nextInt()) fmt.Println(nextInt()) fmt.Println(nextInt()) newInts := intSeq() fmt.Println(newInts()) }

C++

Objective-C

Swift

Kotlin

Java - AnimadorClosure.java

package marcoluglio.generatorexample; // as assinaturas possíveis das closures estão nesse pacote import java.util.function.*; class ClosureState { public int tempoAtual; public float delta; public Float passo; } public class AnimadorClosure { public static Supplier<Float> animar(float inicio, float fim, int tempo) { // variáveis capturadas na closure final ClosureState closureState = new ClosureState(); closureState.tempoAtual = 1; closureState.delta = (fim - inicio) / tempo; closureState.passo = 0; // closure Supplier<Float> lambda = () -> { if (closureState.tempoAtual <= tempo) { closureState.passo = fim - (closureState.delta * (tempo - closureState.tempoAtual)); closureState.tempoAtual += 1; return closureState.passo; } return null; }; return lambda; } }

Java - Main.java

import java.util.function.*; import marcoluglio.generatorexample.AnimadorClosure; public class Main { public static void main(String[] args) { Supplier<Float> animadorClosure = AnimadorClosure.animar(0, 100, 9); Float resultado; do { resultado = animadorClosure.get(); System.out.println(resultado); } while (resultado != null); } } // PS: pra evitar ter que declarar uma classe ClosureState, eu poderia ter feito final Object closureState = new Object() { public int tempoAtual; public float delta; public Float passo; }; // mas aí para ler as propriedades eu teria que usar reflection toda a vez Class ClosureClass = closureState.getClass(); Field TempoAtualField = ClosureClass.getDeclaredField("tempoAtual") TempoAtualField.getInteger(closureState); Field DeltaField = ClosureClass.getDeclaredField("delta") DeltaField.getFloat(closureState); Field PassoField = ClosureClass.getDeclaredField("passo") PassoField.getFloat(closureState);

C# - AnimadorClosure.cs

namespace MarcoLuglio.GeneratorExample { // assinatura da closure public delegate float? Next(); public class AnimadorClosure { public static Next Animar(float inicio, float fim, int tempo) { // variáveis capturadas na closure var tempoAtual = 1; var delta = (fim - inicio) / tempo; var passo = 0f; // closure Next lambda = () => { if (tempoAtual <= tempo) { passo = fim - (delta * (tempo - tempoAtual)); tempoAtual += 1; return passo; } return null; }; return lambda; } } }

C# - MainClass.cs

using System; namespace MarcoLuglio.GeneratorExample { class MainClass { public static void Main(string[] args) { var animadorClosure = AnimadorClosure.Animar(0, 100, 9); float? resultado; do { resultado = animadorClosure(); Console.WriteLine(resultado); } while (resultado != null); } } }

Dart

TypeScript

JavaScript - animarClosure.js

'use strict'; animar(inicio, fim, tempo) { // variáveis capturadas na closure let tempoAtual = 1; let delta = (fim - inicio) / tempo; let passo = 0; // closure let lambda = () => { if (tempoAtual <= tempo) { passo = fim - (delta * (tempo - tempoAtual)); tempoAtual += 1; return passo; } return; }; return lambda; }

JavaScript - main.js

let animadorClosure = animar(0, 100, 9); let resultado; do { resultado = animadorClosure(); console.log(resultado); } while (resultado || resultado === 0);

ActionScript

Python

PHP

VBA / VB6

-

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Functors

Rust

// funcionalidade experimental! // requer versão nightly // para habilitar implementação de FnMut #![feature(fn_traits)] #![feature(unboxed_closures)] struct Animar { fim:f32, tempo:i32, tempoAtual:i32, delta:f32, passo:f32 } impl Animar { fn new(inicio:f32, fim:f32, tempo:i32) -> Animar { Animar { fim, tempo, tempoAtual: 1, delta: (fim - inicio) / (tempo as f32), passo: 0.0 } } } impl FnOnce<()> for Animar { type Output = Option<f32>; extern "rust-call" fn call_once(mut self, _args: ()) -> Self::Output { self() } } impl FnMut<()> for Animar { extern "rust-call" fn call_mut(&mut self, _args: ()) -> Option<f32> { if self.tempoAtual <= self.tempo { let tempoPassado = (self.tempo - self.tempoAtual) as f32; self.passo = self.fim - (self.delta * tempoPassado); self.tempoAtual += 1; return Some(self.passo); } return None; } } fn main() { let mut animar = Animar::new(0.0, 100.0, 9); loop { let resultado = animar(); match resultado { Some(some) => println!("{}", some), None => break } } }

Go

-

C++ - Animar.hpp

#pragma once class Animar final { public: explicit Animar( float inicio, float fim, int tempo ); ~Animar(); // overload de () float operator()(); private: float fim; int tempo; int tempoAtual; float delta; float passo; };

C++ - Animar.cpp

#include "Animar.hpp"; Animar::Animar(float inicio, float fim, int tempo) { this->fim = fim; this->tempo = tempo; tempoAtual = 1; delta = (fim - inicio) / tempo; passo = 0; } ~Animar::Animar(float inicio, float fim, int tempo) { // } // overload de () float Animar::operator()() { if (tempoAtual <= tempo) { passo = fim - (delta * (tempo - tempoAtual)); tempoAtual += 1; return passo; } // TODO selecionar um valor melhor // para indicar o fim return 0; } }

C++ - Animar.hpp

#include "Animar.hpp" int main(int argc, const char* argv[]) { auto animar = Animar(0, 100, 9); while (/* TODO */) { animar(); } return 0; }

Objective-C

-

Swift

// atual não permite overload de () // acompanhe essa proposta

Kotlin

class Animar constructor(inicio:Float, fim:Float, tempo:Int) { var fim:Float var tempo:Int var tempoAtual:Int var delta:Float var passo:Float init { this.fim = fim this.tempo = tempo this.tempoAtual = 1 this.delta = (fim - inicio) / tempo this.passo = 0f } // overload de () operator fun invoke():Float? { if (this.tempoAtual <= this.tempo) { this.passo = this.fim - (this.delta * (this.tempo - this.tempoAtual)) this.tempoAtual += 1 return passo } // TODO selecionar um valor melhor // para indicar o fim return null } } fun main() { var animar = Animar(0f, 100f, 9) do { val resultado = animar() println(resultado) } while (resultado != null) }

Java

-

C#

-

Dart

TypeScript

JavaScript

-

ActionScript

Python

class Animar(object): def __init__(self, inicio, fim, tempo): self.fim = fim self.tempo = tempo self.tempoAtual = 1 self.delta = (fim - inicio) / tempo self.passo = 0 def __call__(self): if (self.tempoAtual <= self.tempo): self.passo = self.fim - (self.delta * (self.tempo - self.tempoAtual)) self.tempoAtual += 1 return self.passo return None animar = Animar(0, 100, 9) while True: result = animar() if result is None: break print(result)

PHP

VBA / VB6

-

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Structs ou classes

Rust

Go

C++

Objective-C

Swift

Kotlin

Java - AnimadorIterator.java

package marcoluglio.generatorexample; import java.util.Iterator; public class AnimadorIterator implements Iterable<Float>, Iterator<Float> { public AnimadorIterator(float inicio, float fim, int tempo) { this.fim = fim; this.tempo = tempo; this.delta = (fim - inicio) / tempo; this.reset(); } // region Interface Iterable<T> @Override // "implementação explícita" public Iterator<Float> iterator() { return this; } // endregion // region Interface Iterator<T> @Override // "implementação explícita" public boolean hasNext() { if (this.tempoAtual <= this.tempo) { return true; } return false; } @Override // "implementação explícita" public Float next() { this.passo = this.fim - (this.delta * (this.tempo - this.tempoAtual)); this.tempoAtual += 1; return this.passo; } // endregion private void reset() { this.tempoAtual = 1; this.passo = 0; } private final int tempo; private int tempoAtual; private final float fim; private final float delta; private float passo; }

Java - Main.java

import marcoluglio.generatorexample.AnimadorIterator; public class Main { public static void main(String[] args) { AnimadorIterator animadorIterador = new AnimadorIterator(0, 100, 9); for (float resultado : animadorIterador) { System.out.println(resultado); } } }

C# - AnimadorIterator.cs

using System.Collections.Generic; namespace MarcoLuglio.GeneratorExample { public class AnimadorIterator : IEnumerable<float>, IEnumerator<float> { public AnimadorIterator(float inicio, float fim, int tempo) { this.fim = fim; this.tempo = tempo; this.delta = (fim - inicio) / tempo; this.Reset(); } #region interface IEnumerable public IEnumerator<float> GetEnumerator() { // implementação implícita return this; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this; // implementação explícita --^ } #endregion #region interface IEnumerator public bool MoveNext() { // implementação implícita if (this.tempoAtual <= this.tempo) { this.passo = this.fim - (this.delta * (this.tempo - this.tempoAtual)); this.tempoAtual += 1; return true; } return false; } public float Current { // implementação implícita get { return this.passo; } } object System.Collections.IEnumerator.Current { // implementação explícita get { return this.passo; } } public void Reset() { // implementação implícita this.tempoAtual = 1; this.passo = 0; } public void Dispose() { /**/ } // implementação implícita #endregion private readonly int tempo; private int tempoAtual; private readonly float fim; private readonly float delta; private float passo; } }

C# - MainClass.cs

using System; namespace MarcoLuglio.GeneratorExample { class MainClass { public static void Main(string[] args) { var animadorIterator = new AnimadorIterator(0, 100, 9); foreach (var resultado in animadorIterator) { Console.WriteLine(resultado); } } } }

Dart

TypeScript

JavaScript - Iterator.js

class AnimadorIterator { constructor(inicio, fim, tempo) { Object.defineProperties(this, { _fim: {value: fim}, _tempo: {value: tempo}, _tempoAtual: {value: tempo, writable: true}, _delta: {value: (fim - inicio / tempo)}, _passo: {value: 0, writable: true} }); Object.seal(this); this.reset(); } reset() { this._tempoAtual = 1; this._passo = 0; } // iterador for of *[Symbol.iterator]() { if (this._tempoAtual <= this.tempo) { this._passo = this._fim - (this._delta * (this._tempo - this._tempoAtual)); this._tempoAtual += 1; yield this._passo; } } }

JavaScript - main.js

let animadorIterator = new AnimadorIterator(0, 100, 9); for (let resultado of animadorIterator) { console.log(resultado); }

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

  1. a

A

Observer (eventos, callbacks e delegates)

Rust

Go

C++

Objective-C

Swift

Kotlin

Java

C# - Subject.cs

// C# idiomatic (delegates) namespace ObserverPattern { // delegate method signature for custom events public delegate void DelegateHandler(Object sender, CustomEventArgs e); public sealed class Subject { // there are many ways which we can define an event delegate function in C# // uses default method signature public event EventHandler StandardEventChanged = delegate {}; // uses raw method signature public event EventHandler<CustomEventArgs> CustomEventChanged = delegate {}; // uses delegate signature alias public event DelegateHandler DelegateChanged = delegate {}; // Action used as alias for EventHandler signature public event Action<object?, CustomEventArgs> ActionAliasEventChanged = (sender, e) => {}; // generic Action signature public event Action<int, bool> GenericActionEventChanged = (value1, value2) => {}; // the “event” properties will only have values assigned if // we init them with a lambda, anonymous delegate funtion, // reference to a function or when a delegate method is // registered for them using += // which is why we need to check for null before invoking it // if we didn’t previously initialized them // there’s also a couple of ways to call the registered delegates // we can mix and match how we init and call them. private void StandardInvoke() { // call .Invoke (does not use reflection, DynimicInvoke does, however) this.StandardEventChanged.Invoke(this, EventArgs.Empty); } private void CustomInvoke(int customProperty) { // call ?.Invoke for checking if we have delegates // before trying to execute them // wouldn’t be necessary since we initilized the event // with a lambda, but I’m leaving this as an example var customEventArgs = new CustomEventArgs(); customEventArgs.CustomProperty = customProperty; this.CustomEventChanged?.Invoke(this, customEventArgs); } private void DelegateInvoke(int customProperty) { // call it as if it was a simple function var customEventArgs = new CustomEventArgs(); customEventArgs.CustomProperty = customProperty; this.DelegateChanged(this, customEventArgs); } private void ActionAliasInvoke(int customProperty) { // check if we have delegates before trying to // call them as a simple function var customEventArgs = new CustomEventArgs(); customEventArgs.CustomProperty = customProperty; if (this.ActionAliasEventChanged != null) { this.ActionAliasEventChanged(this, customEventArgs); } } private void GenericActionInvoke(int customProperty) { this.GenericActionEventChanged.Invoke(1, true); } } }

C# - CustomEvent.cs

namespace ObserverPattern { public sealed class CustomEventArgs : EventArgs { public int CustomProperty { get; set; } } }

C# - Program.cs

using ObserverPattern; void Subject_Changed(object? sender, EventArgs e) { Console.WriteLine(@"Event handler"); } void Subject_CustomEventChanged(object? sender, CustomEventArgs e) { Console.WriteLine(e.CustomProperty); } void Subject_ActionAliasEventChanged(object? sender, CustomEventArgs e) { Console.WriteLine(e.CustomProperty); } void Subject_GenericActionEventChanged(int arg1, bool arg2) { Console.WriteLine(arg1.ToString(), arg2); } var subject = new Subject(); subject.StandardEventChanged += Subject_Changed; subject.CustomEventChanged += Subject_CustomEventChanged; subject.ActionAliasEventChanged += Subject_ActionAliasEventChanged; subject.GenericActionEventChanged += Subject_GenericActionEventChanged; // using a lambda subject.CustomEventChanged += (object? sender, CustomEventArgs e) => { Console.WriteLine(e.CustomProperty); };

C# - Observer.cs

// C# observer interfaces namespace ObserverPattern { public sealed class Observer<T> : IObserver<T> { #region IObserver<T> interface public void OnCompleted() { throw new NotImplementedException(); } public void OnError(Exception error) { throw new NotImplementedException(); } public void OnNext(T value) { Console.WriteLine(value); } #endregion } }

C# - Observable.cs

namespace ObserverPattern { public sealed class Observable<T> : IObservable<T> { List<IObserver<T>> observers; public Observable() { this.observers = new List<IObserver<T>>(); } // this is what will broadcast the updates to observers // it should be called whenever the value changes in the subject // my be hard to fit this in a generic class private void Invoke(T value) { foreach (var observer in this.observers) { observer.OnNext(value); } } #region IObservable<T> interface public IDisposable Subscribe(IObserver<T> observer) { if (!this.observers.Contains(observer)) { this.observers.Add(observer); } var unsubscriber = new Unsubscriber<T>(observers, observer); return unsubscriber; } #endregion } }

C# - Unsubcriber.cs

namespace ObserverPattern { internal sealed class Unsubscriber<T> : IDisposable { private List<IObserver<T>> observers; private IObserver<T> observer; public Unsubscriber(List<IObserver<T>> observers, IObserver<T> observer) { this.observers = observers; this.observer = observer; } public void Dispose() { if (!(this.observer == null)) { this.observers.Remove(this.observer); } } } }

C# - Program.cs

// C# observable collections // usually used along UI using ObserverPattern; var observableSubject = new Observable<Subject>(); var observer = new Observer<Subject>(); observableSubject.Subscribe(observer); // call something on observableSubject that triggers invoke

C#

// C# observable collections using System.Collections.ObjectModel; using System.Collections.Specialized; void ObservableCollection_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { // get e.Action and collection indexes to // find which items where added or removed } var observableCollection = new ObservableCollection<Subject>(); observableCollection.CollectionChanged += ObservableCollection_CollectionChanged; observableCollection.Add(new Subject()); // C# also has an interface called INotifyPropertyChanged // but this one is more commonly used with UI components

Dart

TypeScript

JavaScript

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format - main.wasm

LLVM IR

Assembly

Corrotinas (futures, tasks, promises, deferreds, await, green threads…)

Rust

Go

package main import ( "fmt" "sync" ) // exemplo go routines e channels func fibonacci(c, quit chan int) { x, y := 0, 1 for { select { case c <- x: x, y = y, x + y case <- quit: fmt.Println("quit") return } } } // exemplo WaitGroup type httpPkg struct{} func (httpPkg) Get(url string) {} var http httpPkg func main() { // go routines e channels para comunicação c := make(chan int) quit := make(chan int) go func() { for i := 0; i < 10; i++ { fmt.Println(<- c) } quit <- 0 }() fibonacci(c, quit) // WaitGroup do pacote sync var wg sync.WaitGroup var urls = []string { "http://www.golang.org/", "http://www.google.com/", "http://www.somestupidname.com/", } for _, url := range urls { wg.Add(1) go func(url string) { defer wg.Done() http.Get(url) }(url) } // Espera todos os itens serem completados wg.Wait() }

C++ - main.cpp

#include <iostream> #include <future> #include <boost/algorithm/string.hpp> #include "taskFunction.hpp" int main(int argc, const char* argv[]) { using std::async; using std::string; using std::cout; using std::endl; using MarcoLuglio::TaskExample::taskFunction; // alternativa 1: método // TODO // alternativa 2: função auto functionFuture = async(taskFunction, "função"); // alternativa 3: lambda auto lambdaFuture = async([](string element) -> string { boost::to_upper(element); return element; }, "lambda"); // espera os Futures calcularem um valor // concreto antes de prosseguir cout << functionFuture.get() << endl; cout << lambdaFuture.get() << endl; // c++20+ tem co_return e co_await return 0; }

C++ - taskFunction.hpp

#pragma once #include <string> namespace MarcoLuglio { namespace TaskExample { using std::string; string taskFunction(string element); } }

C++ - taskFunction.cpp

#include <boost/algorithm/string.hpp> #include "taskFunction.hpp" namespace MarcoLuglio { namespace TaskExample { using std::string; string taskFunction(string element) { boost::to_upper(element); return element; } } }

Objective-C

-

Swift - Console

// async await - swift 5.5+ func someFunction() async throws -> [Int] { try await someOtherFunction() return 1 } // TODO use detach to call async from sync // libdispatch ou Grande Central Dispatch import Dispatch // funções auxiliares para simplificar sincronização func check(semaforo:dispatch_semaphore_t) -> Int { let waitResult = dispatch_semaphore_wait( semaforo, dispatch_time(DISPATCH_TIME_NOW, 1_000_000_000) ) return waitResult } func wait(semaforo:dispatch_semaphore_t) { while check(semaforo) != 0 { /**/ } } // tasks var element = "lambda" let utilityQueue = dispatch_get_global_queue( QOS_CLASS_UTILITY, 0 ) let semaforo = dispatch_semaphore_create(0) dispatch_async(utilityQueue) { element = element.uppercaseString print(element) dispatch_semaphore_signal(semaforo) } // espera os blocos terminarem antes de prosseguir wait(semaforo) /* Os tipos pré-definidos de queues são: QOS_CLASS_USER_INTERACTIVE - if it should not cause the ui to lag or hang QOS_CLASS_USER_INITIATED - if is started by ui interaction such as a click QOS_CLASS_UTILITY - if it is a slow operation such as io QOS_CLASS_BACKGROUND - background tasks */

Swift - UI

// libdispatch ou Grande Central Dispatch import Dispatch // funções auxiliares para simplificar sincronização func check(semaforo:dispatch_semaphore_t) -> Int { let waitResult = dispatch_semaphore_wait( semaforo, dispatch_time(DISPATCH_TIME_NOW, 1_000_000_000) ) return waitResult } func wait(semaforo:dispatch_semaphore_t) { while check(semaforo) != 0 { /**/ } } // tasks var element = "lambda" let utilityQueue = dispatch_get_global_queue( QOS_CLASS_UTILITY, 0 ) let semaforo = dispatch_semaphore_create(0) dispatch_async(utilityQueue) { element = element.uppercaseString let mainQueue = dispatch_get_main_queue() dispatch_async(mainQueue) { print(element) dispatch_semaphore_signal(semaforo) } } // espera os blocos terminarem antes de prosseguir wait(semaforo)

Kotlin

import kotlinx.coroutines.* // runBlocking turns main into an async function fun main() = runBlocking { val deferred: Deferred = async { loadData() } println("waiting...") println(deferred.await()) } suspend fun loadData(): Int { println("loading...") delay(1000L) println("loaded!") return 42 } // channels // https://play.kotlinlang.org/hands-on/Introduction%20to%20Coroutines%20and%20Channels/08_Channels // Flow https://kotlinlang.org/docs/reference/coroutines/flow.html#flows

Java - Main.java

import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; public class Main { public static void main(String[] args) { // gerencia threads ExecutorService executor = Executors.newFixedThreadPool(2); // alternativa 1: interface Callable Task callableTask = new Task("async"); Future<String> taskFuture = executor.submit(callableTask); // alternativa 2: lambda Callable String element = "lambda"; Future<String> lambdaFuture = executor.submit(() -> { return element.toUpperCase(); }); // alternativa 3: Threads e Futures manuais sem executor Task manualTask = new Task("manual"); FutureTask<String> manualFuture = new FutureTask<String>(manualTask); new Thread(manualFuture).start(); try { // espera os Futures calcularem um valor // concreto antes de prosseguir System.out.println(taskFuture.get()); System.out.println(lambdaFuture.get()); System.out.println(manualFuture.get()); // encerra as threads do executor executor.shutdown(); } catch (InterruptedException e) { // fazer alguma coisa } catch (ExecutionException e) { // fazer alguma coisa } } }

Java - Task.java

package marcoluglio.taskexample; import java.util.concurrent.Callable; public class Task implements Callable<String> { public Task(String element) { this.element = element; } @Override public String call() throws Exception { return this.element.toUpperCase(); } String element; }

Java Android - AsyncTask.java

// TODO AsyncTask

C# - MainClass.cs

using System; namespace MarcoLuglio.TaskExample { class MainClass { public static void Main(string[] args) { // async não pode ser usado no método // main, então chamamos no objeto // FIXME novas versões podem ter async main var mainObject = new MainClass(); mainObject.main(); } private async void main() { var promise = new Promise(@"some value"); var resultado = await promise.GetResultAsync(); Console.WriteLine(@"esperou " + resultado); } } }

C# - Promise.cs

using System.Threading.Tasks; namespace MarcoLuglio.TaskExample { public class Promise { public Promise(string element) { this.element = element; } public async Task<string> GetResultAsync() { return this.element.ToUpper(); } string element; } }

Dart

// https://pub.dev/documentation/threading/latest/

TypeScript

JavaScript

// async await async function workAsync(element) { return element.toUpperCase(); } await workAsync('some value'); // ou workAsync('some value') .then((result) => { console.log(result); }); // explicit promises function workAsync(element) { return new Promise((resolve, reject) => { resolve(element.toUpperCase()); }); } workAsync('some value') .then((result) => { console.log(result); });

ActionScript

Python

import asyncio async def main(): print('hello') await asyncio.sleep(1) print('world') asyncio.run(main())

PHP

VBA / VB6

-

Ada

Object Pascal (Delphi)

// https://stackoverflow.com/questions/3451138/simple-thread-sample-delphi // https://edn.embarcadero.com/article/22411

Ruby

Smalltalk

Common Lisp

Haskell

  1. a

A

Threads

Rust

// queue use std::collections::vec_deque::VecDeque; // threads use std::thread; // channels use std::sync::mpsc::{Sender, Receiver}; use std::sync::mpsc; fn uppercase(c:char) -> char { c.to_uppercase().next().unwrap() } fn main() { let mut model = VecDeque::new(); model.push_back("dislexicos"); model.push_back("devem"); model.push_back("ler"); model.push_back("frases"); model.push_back("assim"); let (senderChannel, receiverChannel) :(Sender<&str>, Receiver<&str>) = mpsc::channel(); // envia dados pelo canal for element in model { senderChannel.send(element); } // fecha o canal drop(senderChannel); // alternativa 1: thread e lambda // move captura as variáveis no mesmo escopo // da closure por valor ao invés de por referência let lambda_thread = thread::spawn(move || { let mut element:&str; let mut elementUppercase:String; // roda até o canal ser fechado for element in receiverChannel { let uppercase:String = element .chars() .map(uppercase) .collect(); println!("{:?}", uppercase); } // poderíamos usar receiverChannel.recv().unwrap() // e receiverChannel.try_recv().unwrap() }); // alternativa 2: Builder e lambda let mut builderElement = "builder"; let builder_thread = thread::Builder::new() .name("builder thread".to_string()) .spawn(move || { let uppercase:String = builderElement .chars() .map(uppercase) .collect(); println!("{:?}", uppercase); }); // espera as threads terminarem antes de prosseguir lambda_thread.join(); builder_thread.unwrap().join(); }

Go

// Não possui threads // mas veja o exemplo // acima para sincronização // de corrotinas

C++ - main.cpp

#include <iostream> #include <thread> #include <boost/algorithm/string.hpp> #include "cout_mutex.hpp" // para simplicidade do exemplo #include "Model.hpp" #include "ParallelWorker.hpp" #include "parallelWorkerFunction.hpp" int main(int argc, const char* argv[]) { using std::string; using std::cout; using std::endl; using std::make_unique; using std::thread; using std::ref; using MarcoLuglio::ThreadExample::Model; using MarcoLuglio::ThreadExample::ParallelWorker; using MarcoLuglio::ThreadExample::parallelWorkerFunction; // memória compartilhada entre as threads // como as threads não viverão mais que // a main thread, posso usar unique_ptr auto dataQueue = make_unique<Model>(); dataQueue.Push("dislexicos"); dataQueue.Push("devem"); dataQueue.Push("ler"); dataQueue.Push("frases"); dataQueue.Push("assim"); // alternativa 1: método auto worker{ParallelWorker(*dataQueue)}; thread parallelThread{&ParallelWorker::Work, worker}; // alternativa 2: função thread functionThread{parallelWorkerFunction, ref(*dataQueue)}; // alternativa 3: lambda thread lambdaThread{[](Model& dataQueue){ string element; auto sair = false; while (!sair) { element = dataQueue.Next(); // deixa a thread terminar naturalmente if (element == "") { sair = true; continue; } boost::to_upper(element); cout_mutex.lock(); cout << element << endl; cout_mutex.unlock(); } }, ref(*dataQueue)}; // espera as threads terminarem antes de prosseguir parallelThread.join(); functionThread.join(); lambdaThread.join(); } // TODO verificar isso tudo // PS: unique_ptr devolve um ponteiro não copiável quando desreferenciado auto dataQueue = make_unique<Model>(); auto copia = *dataQueue; // erro: não copiável // por isso precisamos passar para as threads, um ponteiro do ponteiro // ou uma referência do ponteiro auto referenciaDoPonteiro*& = ref(dataQueue); // ou ainda, uma referência copiável do valor apontado auto referencia& = ref(*dataQueue);

C++ - Model.hpp

#pragma once #include <string> #include <queue> #include <thread> namespace MarcoLuglio { namespace ThreadExample { using std::string; using std::queue; using std::mutex; // C++ possui classes nativas com acesso // sincronizado, mas não as utilizei para // demonstrar o uso de locks manuais class Model final { public: Model(); ~Model(); void Push(string); string Next(); private: queue<string> dataQueue; /// Lock simples explícita para sincronização mutex modelLock; }; } }

C++ - Model.cpp

#include <string> #include <queue> #include <thread> #include "Model.hpp" namespace MarcoLuglio { namespace ThreadExample { using std::string; using std::queue; using std::lock_guard; using std::mutex; Model::Model() { dataQueue = queue<string>(); }; Model::~Model() { // }; void Model::Push(string) { // só a main thread insere, então // não precisa sincronizar dataQueue.push(element); }; string Model::Next() { // sincroniza o acesso das threads lock_guard<mutex> _{modelLock}; if (!dataQueue.empty()) { string element = dataQueue.front(); dataQueue.pop(); return element; } // string não pode ser nullptr em c++ return ""; }; } }

C++ - ParallelWorker.hpp

#pragma once namespace MarcoLuglio { namespace ThreadExample { class Model; class ParallelWorker final { public: explicit ParallelWorker(Model& model); ~ParallelWorker(); void Work(); private: Model* dataQueue; std::string element; /// Flag para término da thread bool sair; }; } }

C++ - ParallelWorker.cpp

#include <iostream> #include <boost/algorithm/string.hpp> #include "cout_mutex.hpp" // para simplicidade do exemplo #include "Model.hpp" #include "ParallelWorker.hpp" namespace MarcoLuglio { namespace ThreadExample { using std::cout; using std::endl; ParallelWorker::ParallelWorker(Model& model) { dataQueue = &model; sair = false; }; ParallelWorker::~ParallelWorker() { // }; void ParallelWorker::Work() { while (!sair) { element = dataQueue->Next(); // deixa a thread terminar naturalmente if (element == "") { sair = true; continue; } boost::to_upper(element); cout_mutex.lock(); cout << element << endl; cout_mutex.unlock(); } }; } }

C++ - parallelWorkerFunction.hpp

#pragma once namespace MarcoLuglio { namespace ThreadExample { class Model; void parallelWorkerFunction(Model& dataQueue); } }

C++ - parallelWorkerFunction.cpp

#include <iostream> #include <boost/algorithm/string.hpp> #include "cout_mutex.hpp" // para simplicidade do exemplo #include "Model.hpp" #include "parallelWorkerFunction.hpp" namespace MarcoLuglio { namespace ThreadExample { using std::string; using std::cout; using std::endl; void parallelWorkerFunction(Model& dataQueue) { string element; auto sair = false; while (!sair) { element = dataQueue.Next(); // deixa a thread terminar naturalmente if (element == "") { sair = true; continue; } boost::to_upper(element); cout_mutex.lock(); cout << element << endl; cout_mutex.unlock(); } } } }

Objective-C

Swift - Cocoa threads

import Foundation func join(thread:NSThread) { while !thread.finished { /**/ } } public final class NSParallelWorker { @objc public func work() { // deixa a thread terminar naturalmente while !self.sair { print("parallel worker") self.sair = true } } private var sair:Bool = false } // foundation thread com métodos let nsParallelWorker = NSParallelWorker() let selector = #selector(NSParallelWorker.work) let nsThread:NSThread = NSThread.init( target: nsParallelWorker, selector: selector, object: nil ) nsThread.start() // espera as threads terminarem antes de prosseguir join(nsThread)

Swift - POSIX threads

//int threadError = pthread_create( // &posixThreadID, // &attr, // &PosixThreadMainRoutine, // NULL // ); let pThread:pthread_t; let pThreadAttr:pthread_attr_t; pthread_attr_init(UnsafeMutablePointer<pthread_attr_t>(pThreadAttr)) let threadError = pthread_create( UnsafeMutablePointer<pthread_t>(pThread), UnsafePointer<pthread_attr_t>(pThreadAttr), {(UnsafeMutablePointer<Void>) -> UnsafeMutablePointer<Void> in //code }, nil) // let modelLock:pthread_mutex_t = // pthread_join( // pThread, // UnsafeMutablePointer<UnsafeMutablePointer<Void>> // );

Kotlin - main.kt

import marcoluglio.threadexample.* fun main() { // memória compartilhada entre as threads val dataQueue = Model() dataQueue.push("dislexicos") dataQueue.push("devem") dataQueue.push("ler") dataQueue.push("frases") dataQueue.push("assim") // alternativa 1: subclasse de Thread val parallelThread = ParallelThread(dataQueue) parallelThread.start() // alternativa 2: interface Runnable val parallelRunnable:Runnable = ParallelRunnable(dataQueue) val parallelRunnableThread = Thread(parallelRunnable) parallelRunnableThread.start() // alternativa 3: lambda Runnable // ou interface funcional Runnable val lambda = Runnable { var element:String? var sair = false while (!sair) { // dataQueue capturado pelo lambda element = dataQueue.next() // deixa a thread terminar naturalmente if (element == null) { sair = true continue } println(element.toUpperCase()) } } val lambdaRunnable = Thread(lambda) lambdaRunnable.start() // espera as threads terminarem antes de prosseguir try { parallelThread.join() parallelRunnableThread.join() lambdaRunnable.join() } catch (e:InterruptedException) { // fazer alguma coisa } }

Kotlin - Model.kt

package marcoluglio.threadexample import kotlin.collections.ArrayList public class Model { private var dataQueue = ArrayList<String>() // Lock simples explícita para sincronização private val modelLock:Any init { this.modelLock = Any() //this.dataQueue = new LinkedList<String>(); } public fun push(element:String) { // só a main thread insere, então // não precisa sincronizar this.dataQueue.add(element) } public fun next(): String? { synchronized(this.modelLock) { if (this.dataQueue.count() > 0) return this.dataQueue.removeAt(0) else return null } } }

Kotlin - ParallelThread.kt

package marcoluglio.threadexample public class ParallelThread(dataQueue:Model) : Thread() { private val dataQueue: Model private var element: String? = null // Flag para término da thread private var sair = false init { this.dataQueue = dataQueue } public override fun run() { while (!this.sair) { this.element = this.dataQueue.next(); // deixa a thread terminar naturalmente if (this.element == null) { this.sair = true; continue; } println(this.element?.toUpperCase()); } } }

Kotlin - ParallelRunnable.kt

package marcoluglio.threadexample public class ParallelRunnable(dataQueue:Model) : Runnable { private val dataQueue: Model private var element: String? = null // Flag para término da thread private var sair = false init { this.dataQueue = dataQueue } public override fun run() { while (!this.sair) { this.element = this.dataQueue.next(); // deixa a thread terminar naturalmente if (this.element == null) { this.sair = true; continue; } println(this.element?.toUpperCase()); } } }

Java - Main.java

public class Main { public static void main(String[] args) { // memória compartilhada entre as threads Model dataQueue = new Model(); dataQueue.push("dislexicos"); dataQueue.push("devem"); dataQueue.push("ler"); dataQueue.push("frases"); dataQueue.push("assim"); // alternativa 1: subclasse de Thread ParallelThread parallelThread = new ParallelThread(dataQueue); parallelThread.start(); // alternativa 2: interface Runnable Runnable parallelRunnable = new ParallelRunnable(dataQueue); Thread parallelRunnableThread = new Thread(parallelRunnable); parallelRunnableThread.start(); // alternativa 3: lambda Runnable // ou interface funcional Runnable Runnable lambda = () -> { String element; boolean sair = false; while (!sair) { // dataQueue capturado pelo lambda element = dataQueue.next(); // deixa a thread terminar naturalmente if (element == null) { sair = true; continue; } System.out.println(element.toUpperCase()); } }; Thread lambdaRunnable = new Thread(lambda); lambdaRunnable.start(); // espera as threads terminarem antes de prosseguir try { parallelThread.join(); parallelRunnableThread.join(); lambdaRunnable.join(); } catch (InterruptedException e) { // fazer alguma coisa } } }

Java - Model.java

package marcoluglio.threadexample; import java.util.LinkedList; // Java possui classes nativas com acesso // sincronizado, mas não as utilizei para // demonstrar o uso de locks manuais public final class Model { public Model() { this.modelLock = new Object(); this.dataQueue = new LinkedList<String>(); } public void push(String element) { // só a main thread insere, então // não precisa sincronizar this.dataQueue.add(element); } public String next() { // sincroniza o acesso das threads synchronized(this.modelLock) { return this.dataQueue.poll(); } } private LinkedList<String> dataQueue; // Lock simples explícita para sincronização private final Object modelLock; }

Java - ParallelThread.java

package marcoluglio.threadexample; public final class ParallelThread extends Thread { public ParallelThread(Model dataQueue) { this.dataQueue = dataQueue; } // método "main" da thread @Override public void run() { while (!this.sair) { this.element = this.dataQueue.next(); // deixa a thread terminar naturalmente if (this.element == null) { this.sair = true; continue; } System.out.println(this.element.toUpperCase()); } } private Model dataQueue; private String element; // Flag para término da thread private boolean sair = false; }

Java - ParallelRunnable.java

package marcoluglio.threadexample; public final class ParallelRunnable implements Runnable { public ParallelRunnable(Model dataQueue) { this.dataQueue = dataQueue; } // método "main" da thread @Override public void run() { while (!this.sair) { this.element = this.dataQueue.next(); // deixa a thread terminar naturalmente if (this.element == null) { this.sair = true; continue; } System.out.println(this.element.toUpperCase()); } } private Model dataQueue; private String element; // Flag para término da thread private boolean sair = false; }

C# - MainClass.cs

using System; using System.Threading; namespace MarcoLuglio.ThreadExample { public class MainClass { public static void Main(string[] args) { // memória compartilhada entre as threads var dataQueue = new Model(); dataQueue.Push("dislexicos"); dataQueue.Push("devem"); dataQueue.Push("ler"); dataQueue.Push("frases"); dataQueue.Push("assim"); // alternativa 1: método var worker = new ParallelWorker(dataQueue); var parallelThread = new Thread(worker.Work); parallelThread.Start(); // alternativa 2: lambda var lambdaThread = new Thread(() => { string element; var sair = false; while (!sair) { // dataQueue capturado pelo lambda element = dataQueue.Next(); // deixa a thread terminar naturalmente if (element == null) { sair = true; continue; } Console.WriteLine(element.ToUpper()); } }); lambdaThread.Start(); // espera as threads terminarem antes de prosseguir parallelThread.Join(); lambdaThread.Join(); } } }

C# - Model.cs

using System.Collections.Generic; namespace MarcoLuglio.ThreadExample { // C# possui classes nativas com acesso // sincronizado, mas não as utilizei para // demonstrar o uso de locks manuais public sealed class Model { public Model() { this.modelLock = new object(); this.dataQueue = new Queue<string>(); } public void Push(string element) { // só a main thread insere, então // não precisa sincronizar this.dataQueue.Enqueue(element); } public string Next() { // sincroniza o acesso das threads lock (this.modelLock) { if (this.dataQueue.Count == 0) { return null; } return this.dataQueue.Dequeue(); } } private readonly Queue<string> dataQueue; /// <summary> /// Lock simples explícita para sincronização /// </summary> private readonly object modelLock; } }

C# - ParallelWorker.cs

using System; namespace MarcoLuglio.ThreadExample { public sealed class ParallelWorker { public ParallelWorker(Model dataQueue) { this.dataQueue = dataQueue; } // método "Main" da thread public void Work() { while (!this.sair) { this.element = this.dataQueue.Next(); // deixa a thread terminar naturalmente if (this.element == null) { this.sair = true; continue; } Console.WriteLine(this.element.ToUpper()); } } private Model dataQueue; private string element; /// <summary> /// Flag para término da thread /// </summary> private bool sair = false; } }

JavaScript - main.js

'use strict'; // cria a worker thread de uso exclusivo // da main thread let webWorker = new Worker('worker.js'); // web workers não compartilham memória // apenas trocam mensagens entre si // e não podem acessar o DOM // envia mensagens para a worker thread webWorker.postMessage(['algum', 'valor']); webWorker.postMessage([10, 20]); // callback para recepção de mensagens // da worker thread webWorker.onmessage = (event) => { console.log(event.data); }; // mata a thread imediatamente se quiser // webWorker.terminate();

JavaScript - worker.js

'use strict'; // callback para recepção de mensagens // da main thread (ui thread) onmessage = (event) => { console.log(event.data[0]); console.log(event.data[1]); let result = event.data.join(' '); // envia mensagens para a main thread postMessage(result); // termina a thread se quiser // close(); };

Dart

TypeScript

JavaScript - sharedThread1.js

'use strict'; // cria uma worker thread compartilhada let webWorkerOp1 = new SharedWorker('worker.js'); // envia mensagens para a worker thread compartilhada webWorkerOp1.port.postMessage(['algum', 'valor']); webWorkerOp1.port.postMessage([10, 20]); // callback para recepção de mensagens // da worker thread webWorkerOp1.port.onmessage = (event) => { console.log(event.data); };

JavaScript - sharedThread2.js

'use strict'; // cria uma worker thread compartilhada let webWorkerOp2 = new SharedWorker('worker.js'); // envia mensagens para a worker thread compartilhada webWorkerOp2.port.postMessage(['misturar', 2]); webWorkerOp2.port.postMessage([10, 20]); // callback para recepção de mensagens // da worker thread webWorkerOp2.port.onmessage = (event) => { console.log(event.data); };

JavaScript - worker.js

'use strict'; onconnect = (event) => { let port = event.ports[0]; // callback para recepção de mensagens // da main thread (ui thread) port.onmessage = (event) => { console.log(event.data[0]); console.log(event.data[1]); let result = event.data.join(' '); // envia mensagens para a main thread port.postMessage(result); // termina a thread se quiser // close(); }; };

ActionScript

Python

import threading import time class myThread (threading.Thread): def __init__(self, threadID, name): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter def run(self): threadLock.acquire() # TODO threadLock.release() threadLock = threading.Lock() threads = [] thread1 = myThread(1, 'Thread-1') thread2 = myThread(2, 'Thread-2') threads.append(thread1) threads.append(thread2) for t in threads: t.start() for t in threads: t.join() #def main(): # x = threading.Thread(target=thread_function, args=(1,)) # x.start() # x.join()

PHP

VBA / VB6

-

Ada

// https://learn.adacore.com/courses/Ada_For_The_CPP_Java_Developer/chapters/11_Concurrency.html

Object Pascal (Delphi)

Ruby

# https://ruby-doc.org/core-2.5.0/Thread.html

Smalltalk

Common Lisp

Haskell

  1. C#
  2. C++
  3. JavaScript
  4. Java

A

Diretivas do compilador / Pré-processador

Rust

// TODO rust tem vários atributos // TODO macros também são pré-processados // compilação condicional com #cfg é um deles // copiado de rust by example e docs oficiais #[cfg(...)] #[cfg(target_os = "macos")] #[cfg(any(foo, bar))] #[cfg(all(unix, target_pointer_width = "32"))] #[cfg(not(foo))] #[cfg(target_os = "linux")] fn are_you_on_linux() { println!("You are running linux!") } // function only gets compiled if target OS is *not* linux #[cfg(not(target_os = "linux"))] fn are_you_on_linux() { println!("You are *not* running linux!") } fn main() { are_you_on_linux(); println!("Are you sure?"); if cfg!(target_os = "linux") { println!("Yes. It's definitely linux!"); } else { println!("Yes. It's definitely *not* linux!"); } } /* debug_assertions - Enabled by default when compiling without optimizations. This can be used to enable extra debugging code in development but not in production. For example, it controls the behavior of the standard library's debug_assert! macro. target_arch = "..." - "x86", "x86_64", "mips", "powerpc", "powerpc64", "arm", or "aarch64". target_endian = "..." - "little", "big". target_env = ".." - musl, msvc, gnu or blank target_family = "..." - "unix" or "windows". target_os = "..." - "windows", "macos", "ios", "linux", "android", "freebsd", "dragonfly", "bitrig" , "openbsd" or "netbsd". target_pointer_width = "..." - "32" or "64" target_vendor = "..." - apple, pc, "unknown". test - Enabled when compiling the test harness (using the --test flag). unix - See target_family. windows - See target_family. */

Go

//go:noescape //go:uintptrescapes //go:noinline //go:norace //go:nosplit //go:linkname localname [importpath.name] //line :line //line :line:col //line filename:line //line filename:line:col /*line :line*/ /*line :line:col*/ /*line filename:line*/ /*line filename:line:col*/

C++

#include <iostream> #include "somelib.h" #pragma once #ifndef __some_identifier__ #define __some_identifier__ // rest of code #endif

Objective-C

#include <iostream> #include "somelib.h" #ifndef __some_identifier__ #define __some_identifier__ // rest of code #endif

Swift

/* os() OSX, iOS, watchOS, tvOS, Linux arch() x86_64, arm, arm64, i386 swift() >= followed by a version number */ #if os(iOS) && !swift(>= 2) // statements #elseif os(OSX) // statements #else // statements #endif

Kotlin

-

Java

-

C#

// não podem ter whitespace antes! #if DEBUG // #elif TRACE // #else // #endif // TODO ver oq o visual studio fornece #define TESTE #if TESTE #warning TESTE is defined // ou #error TESTE is defined #endif #undef TESTE // desabilitar avisos do compilador #pragma warning disable 414, 3021 [CLSCompliant(false)] public class C { static void Main() {} } #pragma warning restore 414, 3021 // garantir checksums de arquivos #pragma checksum "filename.cs" "{3673e4ca-6098-4ec1-890f-8fceb2a794a2}" "{012345678AB}" // guid --^ checksum bytes --^ // #line é mais usado por source generators // força step over pelo debugger #line hidden #line 837 "Meio inútil" #line default

Dart

TypeScript

/// <reference path="…" /> /// <reference types="…" /> /// <reference lib="…" /> /// <reference no-default-lib="true" /> /// <amd-module /> /// <amd-dependency />

JavaScript

'use strict'; // modo estrito

ActionScript

Python

PHP

VBA / VB6

Option Compare Option Explicit #Const DEBUG = 1 #If DEBUG = 1 Then 'Código de debug #Else 'Código normal #End If

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

  1. a

A

Tuples

Rust

let some_tuple = (1u8, 2u16, 2f32); some_tuple.0;

Go

-

C++

#include <tuple> auto valores{std::make_tuple(3.8, 'A', "Lisa Simpson")}; auto valoresCpp17{1, -1}; std::get<0>(valores);

Objective-C

-

Swift

let someTuple: (Double, Double, Double) = (3.14159, 2.71828, 1.1) someTuple.0 // lembrando que uma tuple vazia em swift significa Void // () > () // () > Void

Kotlin

Java

-

C#

// tuple literals - C# 7+ var population = ("New York", 7891957, 7781984); // com índices // TODO verificar isso var population = (a:"New York", b:7891957, c:7781984); // com nomes // TODO verificar isso // tuple classes var population = new Tuple<string, int, int>("New York", 7891957, 7781984); population.Item1;

Dart

TypeScript

JavaScript

-

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

  1. Rust / Swift
  2. C++ / C#

Rust e Swift lidam com tuples de modo bastante integrado à linguagem.
C++ e C# tratam tuples como se fossem uma funcionalidade construída sobre o paradigma de orientaçµão à objetos.

Enumeradores

Rust

enum WithoutValues { A, B, C } // podemos misturar os tipos enum WithValues { A(i32), B(i32, i32), C(String) } let someEnum = WithValues::B(1, 2);

Go

// use constantes + iota const ( a = 1 << iota // a == 1 (iota has been reset) b = 1 << iota // b == 2 c = 1 << iota // c == 4 )

C++

Objective-C

Swift

enum GamePad { case XboxOne case XboxEliteSeries2 case Dualshock4 case DualSense case JoyCon } // implicit raw values enum PreviousGameConsole:UInt8 { case Xbox360 = 0x00 case PlayStation4 // 0x01 case WiiU // 0x02 } // explicit values enum GameConsole:UInt8 { case XboxSeriesX = 0x00 case PlayStation5 = 0x01 case NintendoSwitch = 0x02 } // to raw value let gameConsole = GameConsoles.NintendoSwitch.rawValue // 0x02 // from raw value let playstation5 = GameConsole(rawValue: 0x01) // associated values of different types enum Barcode { case upc(Int, Int, Int, Int) case qrCode(String) } var productBarcode = Barcode.upc(8, 85909, 51226, 3) productBarcode = .qrCode("ABCDEFGHIJKLMNOP") // iterable enum Beverage:CaseIterable { case coffee, tea, juice } let numberOfChoices = Beverage.allCases.count for beverage in Beverage.allCases { print(beverage) } // recursivamente // TODO

Kotlin

Java

C#

Dart

TypeScript

JavaScript

// ver Symbol

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

  1. a

A

Objetos

Structs

Rust

// Devemos inicializar todos os campos // da struct com a sintaxe de chaves // antes de poder usá-la pub struct ResultadoCaixa { pub total:i32, pub valorPago:i32, pub troco:i32, } let mut compra1 = ResultadoCaixa{ total: 967, valorPago: 1000, troco: 33 }; // structs podem ter métodos // métodos podem ou não modificar a struct // dependendo de como recebem o argumento // self. Se &self ou &mut self impl ResultadoCaixa { pub fn descontarFidelidade(&mut self) { self.total = self.calcularFidelidade(); self.troco = self.valorPago - self.total; } fn calcularFidelidade(&self) -> i32 { self.total - 1 } } // structs não herdam de um objeto comum // Nem suportam herança // No entanto, podem implementar traits trait Parcelavel { fn parcelar(&self) -> [i32; 3]; } impl Parcelavel for ResultadoCaixa { fn parcelar(&self) -> [i32; 3] { // } }

Go

package main import "fmt" type SomeBaseStruct struct { a int32 } // structs não suportam herança // mas tem um atalho para fazer composição type SomeStruct struct { SomeBaseStruct // composição x int32 } // structs podem ter métodos func (s *SomeStruct) getX() int32 { return s.x } func (s *SomeStruct) setX(newValue int32) { s.x = newValue } func setToTen(s *SomeStruct) { s.setX(10) } func main() { s1 := SomeStruct { x: 2, // vírgula dangling não é um erro, é obrigatório } s2 := SomeStruct { x: 2} // ou então } tem que vir na mesma linha // mesmo que c++, se passar por valor faz uma cópia sem avisar setToTen(&s2) fmt.Println(s1.x) fmt.Println(s2.x) }

C++

// structs e classes são idênticas // em C++ exceto por uma única diferença // por padrão os campos das structs são // publicos, e os das classes são privados

Objective-C

// Objective-C usa structs do C // que são um simples agrupamento // de variáveis sem nenhuma outra // funcionalidade extra struct ResultadoCaixa { int total; int valorPago; int troco; }; // sempre que utilizarmos o nome // do tipo definido com uma struct // precisamos incluir a palavra struct // antes do nome do tipo struct ResultadoCaixa compra1 = { .total = 967, .valorPago = 1000, .troco = 33 }; // ou struct ResultadoCaixa compra1; compra1.total = 967; compra1.valorPago = 1000; compra1.troco = 33; // ou ainda struct ResultadoCaixa compra1 = { 967, 1000, 33 };

Swift

// Devemos inicializar todos os campos // da struct com o inicializador gerado // automaticamente antes de poder usá-la public struct ResultadoCaixa { public var total:Int public var valorPago:Int public var troco:Int } let compra1 = ResultadoCaixa( total: 967, valorPago: 1000, troco: 33 ) // structs podem ter métodos // por padrão, métodos não podem modificar a struct // mas podem ser marcados com a palavra mutating // para indicar este intuito public struct ResultadoCaixaFidelidade { public mutating func descontarFidelidade() { self.total = self.calcularFidelidade() self.troco = self.valorPago - self.total } private func calcularFidelidade() -> Int { return total - 1 } public var total:Int public var valorPago:Int public var troco:Int } // structs não herdam de um objeto comum // Nem suportam herança // No entanto, podem implementar protocolos // Embora o resultado seja bastante confuso // em termos de alocação de memória public protocol Parcelavel { func parcelar():[Int] } public struct ResultadoCaixaCartao : Parcelavel { public func parcelar():[Int] { // } }

Kotlin

// data classes NÃO SÃO structs // mas tem um propósito similar public data class ResultadoCaixa( val total:Int, val valorPago:Int, var troco:Int ) val compra1 = ResultadoCaixa( total = 967, valorPago = 1000, troco = 33 )

Java

// java 15+ // records NÃO SÃO structs // mas tem um propósito similar public record ResultadoCaixa( int total, int valorPago, int troco ){} var compra1 = ResultadoCaixa( 967, 1000, 33 );

C#

// Se criada sem new os campos // são iniciados manualmente public struct ResultadoCaixa { public int total; public int valorPago; public int troco; } ResultadoCaixa compra1; compra1.total = 967; // 9,67 compra1.valorPago = 1000; // 10,00 compra1.troco = 33; // 00,33 // Se criada com new os campos // são iniciados no construtor public struct ResultadoCaixaC { ResultadoCaixaC(int total, int valorPago) { this.total = total; this.valorPago = valorPago; this.troco = valorPago - total; } public int total; public int valorPago; public int troco; } var compra2 = new ResultadoCaixaC(967, 1000); // structs podem ter métodos public struct ResultadoCaixaFidelidade { public void descontarFidelidade() { this.total = this.calcularFidelidade(); this.troco = this.valorPago - this.total; } private int calcularFidelidade() { return this.total - 1; } public int total; public int valorPago; public int troco; } // structs herdam de Object Console.WriteLine(resultado is Object); // true // Mas NÃO suportam heranças subsequentes public struct ResultadoCaixaFidelidade2 : ResultadoCaixa {} // erro // No entanto, podem implementar interfaces // Embora o resultado seja bastante confuso // em termos de alocação de memória public interface Parcelavel { int[] Parcelar(); } public struct ResultadoCaixaCartao : Parcelavel { // ok public int[] Parcelar() { // } } // c# 9+ // records NÃO SÃO structs // mas tem um propósito similar // record chegou a ser anunciado como data class antes da versão final public record Person { public string FirstName { get; init; } public string LastName { get; init; } } var person = new Person("Scott", "Hunter"); // positional construction var otherPerson = person with { LastName = "Hanselman" }; // with

Dart

TypeScript

JavaScript

-

ActionScript

Python

# python 3.7+ # data classes NÃO SÃO structs # mas tem um propósito similar @dataclass(eq = True, unsafe_hash = False, frozen = False) class ResultadoCaixa: total:int valorPago:int troco:int compra1 = ResultadoCaixa(967, 1000, 33)

PHP

// acompanhe essa feature // meanwhile use associative arrays // TODO

VBA / VB6

' User Defined Types (UDTs) se parecem com structs 'Definimos o tipo num arquivo .bas separado Public Type ResultadoCaixa Total As Integer ValorPago As Integer Troco As Integer End Type Dim compra1 As ResultadoCaixa compra1.total = 967; ' 9,67 compra1.valorPago = 1000; ' 10,00 compra1.troco = 33; ' 00,33 ' ou com With With compra1 .total = 967; ' 9,67 .valorPago = 1000; ' 10,00 .troco = 33; ' 00,33 End With

Ada

Object Pascal (Delphi)

type TResultadoCaixa = record Total:Integer; ValorPago:Integer; Troco:Integer; end; program Main; var compra1:TResultadoCaixa; begin compra1.Total := 967; compra1.ValorPago := 1000; compra1.Troco := 33; // ou com with with compra1 do begin Total := 967; ValorPago := 1000; Troco := 33; end; end. // structs podem ter a parte final // variável type TResultadoCaixa2 = record fieldList1:type1; ... fieldListn:typen; case tag: ordinalType of constantList1: (variant1); ... constantListn: (variantn); end; // structs podem ter construtores, métodos, getters e setters type TResultadoCaixa3 = record constructor Create(total:Integer, valorPago:Integer); // property RedProperty: TInnerColorType read Red write Red; procedure DescontarFidelidade(); function CalcularFidelidade():Integer; Total:Integer; ValorPago:Integer; Troco:Integer; end; constructor TResultadoCaixa3.Create(Total:Integer, ValorPago:Integer); begin Self.Total := Total; Self.ValorPago := ValorPago; Self.Troco := ValorPago - Total; end; procedure TResultadoCaixa3.DescontarFidelidade; begin Self.Total := Self.CalcularFidelidade(); Self.Troco := Self.ValorPago - Self.Total; end; function TResultadoCaixa3.CalcularFidelidade:Integer; begin Result := Self.Total - 1; end;

Ruby

ResultadoCaixa = Struct.new( :total, :valorPago, :troco ) compra1 = ResultadoCaixa.new( 967, 1000, 33 ) # structs podem ter métodos, getters e setters ResultadoCaixa = Struct.new( :total, :valorPago, :troco ) do def descontarFidelidade self.total = self.calcularFidelidade() # TODO self.troco = self.valorPago - self.total end def calcularFidelidade return self.total - 1 end end

Smalltalk

Common Lisp

Haskell

Comparando structs

Rust

Go

C++

Objective-C

Swift

Kotlin

Java

C#

Dart

TypeScript

JavaScript

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

LLVM IR

Classes

Rust

-

Go

-

C++ - ResultadoCaixa.hpp

#pragma once class ResultadoCaixa final { public: explicit ResultadoCaixa(const int total, const int valorPago); ~ResultadoCaixa(); void descontarFidelidade(); private: // por padrão, métodos podem modificar a classe // mas podem ser marcados com a palavra const // para proibir este intuito int calcularFidelidade() const; int total; int valorPago; int troco; };

C++ - ResultadoCaixa.cpp

#include "ResultadoCaixa.hpp" ResultadoCaixa::ResultadoCaixa(const int total, const int valorPago) : total{total}, valorPago{valorPago} { this->troco = valorPago - total; } ResultadoCaixa::~ResultadoCaixa() { // } ResultadoCaixa::descontarFidelidade() { this->total = calcularFidelidade(); this->troco = valorPago - total; } int ResultadoCaixa::calcularFidelidade() const { return total - 1; }

C++ - main.cpp

#include "ResultadoCaixa.hpp" int main(int argc, const char* argv[]) { // aloca na stack auto compra1 = ResultadoCaixa(997, 1000); compra1.descontarFidelidade(); // aloca na heap auto compra2 = new ResultadoCaixa(997, 1000); compra2.descontarFidelidade(); return 0; }

Objective-C - ResultadoCaixa.h

#import <Foundation/Foundation.h> @interface ResultadoCaixa : NSObject { // instance variables ou ivars @private int _troco; } - (void) descontarFidelidade; - (int) calcularFidelidade; // propriedades @property (assign, nonatomic) int total; @property (assign, nonatomic) int valorPago; @end

Objective-C - ResultadoCaixa.m

#import "ResultadoCaixa.h" @implementation ResultadoCaixa - (id) initWithTotal:(int)novoTotal eValorPago:(int)novoValorPago { [self init]; // propriedades são acessadas com . self.total = novoTotal; self.valorPago = novoValorPago; // ivars são acessadas com -> self->_troco = self.valorPago - self.total; return self; } - (void) descontarFidelidade { self.total = [self calcularFidelidade]; self->_troco = self.valorPago - self.total; } - (int) calcularFidelidade { return self.total - 1; } @end

Objective-C - main.m

#import "ResultadoCaixa.h" int main(int argc, const char* argv[]) { ResultadoCaixa* compra1 = [[ResultadoCaixa alloc] initWithTotal:997 eValorPago:1000]; [compra1 descontarFidelidade]; return 0; }

Swift

public final class ResultadoCaixa { init(total:Int, valorPago:Int) { self.total = total self.valorPago = valorPago self.troco = valorPago - total } public func descontarFidelidade() { self.total = self.calcularFidelidade() self.troco = self.valorPago - self.total } private func calcularFidelidade() -> Int { return self.total - 1 } private var total = 0 private var valorPago = 0 private var troco = 0 } let compra1 = ResultadoCaixa() compra1.descontarFidelidade() class C { static func myStaticMethod() { // } static var myStaticProp:String deinit { // } lazy var prop:String } final class D : C, P, Q { override init() { super.init() } init?() { return nil } convenience init() { // } // o override pode ser mais visível! override internal func myMethod() { super.myMethod() } } final class R { required init() { // } }

Kotlin - ResultadoCaixa.kt

public class ResultadoCaixa(total:Int, valorPago:Int) { public fun descontarFidelidade() { this.total = this.calcularFidelidade(); this.troco = this.valorPago - this.total; } private fun calcularFidelidade():Int { return this.total - 1; } var total = total val valorPago = valorPago var troco = valorPago - total lateinit var prop:String } // OU public class ResultadoCaixa constructor(val total:Int, val valorPago:Int) { init { this.total = total this.valorPago = valorPago this.troco = valorPago - total } public fun descontarFidelidade() { this.total = this.calcularFidelidade(); this.troco = this.valorPago - this.total; } private fun calcularFidelidade():Int { return this.total - 1; } var total:Int val valorPago:Int var troco:Int } val compra1 = ResultadoCaixa(997, 1000) compra1.descontarFidelidade() open class C { } class D : C, P, Q { // }

Kotlin - Main.kt

Java - ResultadoCaixa.java

public final class ResultadoCaixa { public ResultadoCaixa(int total, int valorPago) { this.total = total; this.valorPago = valorPago; this.troco = this.valorPago - this.total; } public void descontarFidelidade() { this.total = this.calcularFidelidade(); this.troco = this.valorPago - this.total; } private int calcularFidelidade() { return this.total - 1; } private int total = 0; // variáveis final não podem ser alteradas // após seu valor ter sido especificado private final int valorPago; private int troco = 0; }

Java - Main.java

public class Main { public static void main(string[] args) { ResultadoCaixa compra1 = new ResultadoCaixa(997, 1000); compra1.descontarFidelidade(); } }

C# - ResultadoCaixa.cs

public sealed class ResultadoCaixa { public ResultadoCaixa(int total, int valorPago) { this.total = total; this.valorPago = valorPago; this.troco = this.valorPago - this.total; } public void descontarFidelidade() { this.total = this.calcularFidelidade(); this.troco = this.valorPago - this.total; } // c# 7 private int calcularFidelidade => this.total - 1; private int total = 0; // propriedades readonly só podem ser modificadas // dentro do construtor private readonly int valorPago; private int troco = 0; }

C# - MainClass.cs

public class MainClass { public static void Main(string[] args) { // argumentos por posição var compra1 = new ResultadoCaixa(997, 1000); compra1.descontarFidelidade(); // argumentos nomeados var compra2 = new ResultadoCaixa(total:997, valorPago:1000); compra2.descontarFidelidade(); } }

Dart

TypeScript

JavaScript

// note que JavaScript não possui classes de verdade // apenas objetos que herdam de outros objetos diretamente // prototype based inheritance const ResultadoCaixa = class ResultadoCaixa { constructor(total, valorPago) { Object.defineProperties(this, { total: {value: total, writable: true}, valorPago: {value: valorPago}, // não writable por padrão troco: {value: valorPago - total, writable: true} }); Object.seal(this); } descontarFidelidade() { this.total = this.calcularFidelidade(); this.troco = this.valorPago - this.total; } calcularFidelidade() { return this.total - 1; } }; const compra1 = new ResultadoCaixa(997, 1000); compra1.descontarFidelidade();

ActionScript

Python

class ResultadoCaixa: def __init__(self, total, valorPago): self.total = total self.valorPago = valorPago self.troco = self.valorPago - self.total def descontarFidelidade(self): self.total = self.calcularFidelidade() self.troco = self.valorPago - self.total def calcularFidelidade(self): return self.total - 1 compra1 = ResultadoCaixa(997, 1000) compra1.descontarFidelidade()

PHP

VBA / VB6 - ResultadoCaixa.cls

'Evento Public Event OnChange(ByVal valorNovo As Byte, ByVal valorAntigo As Byte) 'Variável pública, pode ser acessada diretamente Public publicVar As Boolean 'Variáveis privadas acessadas pelas propriedades Private prop1 As Boolean Private friendProp1 As Boolean 'Getter Public Property Get Prop1() As Boolean Prop1 = prop1 End Property 'Setter de tipos primitivos usa Let Public Property Let Prop1(ByVal value As Boolean) prop1 = value End Property 'Setter de objetos usa Set 'Friend permite acesso por outros objetos do mesmo projeto / dll 'Não tem relação nenhuma com a funcionalidade em c++ Friend Property Get FriendProp1() As Boolean FriendProp1 = friendProp1 End Property Public Sub Metodo1() RaiseEvent OnChange(1, 2) 'Podemos nos registrar para responder à esse evento usando no nosso form 'Private Sub Instance_OnChange(ByVal valorNovo As Byte, ByVal valorAntigo As Byte) '... 'End Sub End Sub Public Function Metodo2() As Boolean '... End Function Friend Function MetodoFriend(Optional ByVal argOpcional1 As Boolean = True) As Boolean '... End Function

VBA / VB6 - Main.bas

Dim compra1 As ResultadoCaixa Set compra1 = new ResutadoCaixa ' TODO

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

(defclass resultadoCaixa() ( (name :initarg :name :accessor name ) (lisper :initform nil :accessor lisper ) ))

Haskell

Comparando objetos

Rust

Go

C++

Objective-C

Swift

Kotlin

Java

C#

Dart

TypeScript

JavaScript

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

LLVM IR

Getters e setters (propriedades)

Rust

-

Go

-

C++

-

Objective-C - A.h

#import <Foundation/Foundation.h> @interface A : NSObject @property (assign, nonatomic) NSString* prop; @property (assign, nonatomic) NSString* prop2; @end

Objective-C - A.m

#import "A.h" @implementation A @end

Objective-C - main.m

#import "A.h" int main(int argc, const char* argv[]) { A* a = [[A alloc] init]; a.prop = @""; return 0; }

Swift

public final class A { init() { // } var getter:String { return ... } var getterSetter:String { get { return self._getterSetter } set(newValue) { // ou newValue implícito set { self._getterSetter = newValue } } private _getterSetter:String // setter pode ser menos visível que o getter public private(set) var numberOfEdits = 0 // internal private(set) var numberOfEdits = 0 } var a = A() a.prop = ""

Kotlin

// as classes são final por padrão // não confundir com sealed class // que quer dizer outra coisa class A { init { // } // getter var stringRepresentation:String get() = this.toString() // getter e setter var stringRepresentation2:String get() = this.toString() set(value) { setDataFromString(value) } // com visibilidades diferentes var stringRepresentation3:String get() = this.toString() private set(value) { setDataFromString(value) } }

Java

// não tem getters e setters implícitos // tem que usar métodos com convenção de nome // começando com Get ou Set

C# - ResultadoCaixa.cs

public sealed class A { public A() { // } public string Prop { get; set; } // c# 7 public string Prop2 { get => ""; set => this.prop2 = value; } public string Prop3 { get { return ""; } set { this.prop3 = value; } } private string prop2; private string prop3; }

C# - MainClass.cs

public class MainClass { public static void Main(string[] args) { // argumentos por posição var a = new A(); a.prop = @""; a.prop2 = @""; } }

Dart

TypeScript

JavaScript

const A = class A { constructor() { Object.defineProperty( this, '_prop', {value: null, writable: true} ); Object.seal(this); } get prop() { return this._prop; } set prop(newValue) { this._prop = newValue; } }; const a = new A(); a.prop = '';

ActionScript

Python

class A: def __init__(self, prop = 0): self.prop = prop @property def prop(self): return self._prop @prop.setter def prop(self, value): self._prop = value

PHP

VBA / VB6

Option Explicit Private m_prop As String Private Sub Class_Initialize() m_name = "" End Sub Public Property Get Prop() as String Prop = m_name End Property Public Property Let Prop(ByVal Value As String) m_prop = Value End Property

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Traits

Rust

trait HasArea { fn is_invalid(&self) -> bool { !self.is_valid() } } impl HasArea for Circle { // is_invalid "herdado" }

Go

// Possui atalhos para composição de objetos

C++

// Herança múltipla tem // funcionalidade similar // às traits

Objective-C - Traits.h

@interface Person (Traits) - (void) addFriend:(Person *)aFriend; - (void) removeFriend:(Person *)aFriend; - (void) sayHelloToFriends; @end

Objective-C - Traits.m

#import "Person+Relations.h" @implementation Person (Traits) - (void) addFriend:(Person*)aFriend { [[self friends] addObject:aFriend]; } - (void) removeFriend:(Person*)aFriend { [[self friends] removeObject:aFriend]; } - (void) sayHelloToFriends { for (Person* friend in [self friends]) { NSLog(@"Hello there, %@!", [friend name]); } } @end

Swift

extension ClassToBeExtended { // posso adicionar initializers // métodos // e propriedades }

Kotlin

fun ClassToBeExtended.extensionMethod() { // } // ou como Java 8 public interface Desenhavel { desenhar() { // } }

Java

public interface Desenhavel { default void desenhar() { // } }

C#

public static class MyExtensions { public static int ExtensionMethod(this ClassToBeExtended str) { // } }

Dart

TypeScript

JavaScript

ActionScript

Python

PHP

VBA / VB6

-

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Interfaces

Rust

trait HasArea { fn area(&self) -> f64; } impl HasArea for Circle { fn area(&self) -> f64 { std::f64::consts::PI * (self.radius * self.radius) } }

Go

// Se uma struct possui todos os métodos // listados na interface, ele automaticamente // implementa uma interface sem precisar // declarar explicitamente import ( "math" ) type HasArea interface { Area() float64 } type Circle struct { radius float64 } func (c *Circle) Area() float64 { return math.Pi * (c.radius * c.radius) }

C++

// use herança múltipla

Objective-C

@protocol A - (NSInteger)requiredMethod; - (NSInteger)anotherRequiredMethod; @property (nonatomic, assign) NSInteger aProp; @optional - (NSInteger)optionalMethod; // required methods again @required - (NSInteger)requireMethodAfterOptional; @end @protocol B // @end @protocol C <A> // @end @protocol D <A, B> // @end @interface : NSObject <C, D> @synthesize aProp @end

Swift

// public internal private // interfaces protocol P { // pode conter variáveis e métodos func someMethod() -> int } protocol Q { // } // implementação default // com extension methods extension P { // where Element: Equatable { // podemos passar condições se precisar func someMethod() -> { return 1 } } // structs struct S : P, Q { // para structs, o padrão dos métodos // é ser const func constMethod() { // } mutating func structMethod() { // } } final class D : C, P, Q { override init() { super.init() } init?() { return nil } convenience init() { // } // o override pode ser mais visível! override internal func myMethod() { super.myMethod() } } let o2 = D()

Kotlin

interface A { fun foo() { print("A") } fun bar() val prop:Int // abstract val propertyWithImplementation:String get() = "foo" } interface B { fun foo() { print("B") } fun bar() { print("bar") } } interface I : B { // } class C : A { override fun bar() { print("bar") } } class D : A, B { override fun foo() { super<A>.foo() super<B>.foo() } // se as interfaces tiverem // implementações default // de métodos com a mesma assinatura // é obrigatório redefiní-lo na classe override fun bar() { super<B>.bar() } }

Java

interface A { // método estático static public int someStaticMethod() { return 1; } // método virtual int someMethod(); } interface B { // método virtual int someOtherMethod(); // método default // é sempre público também // java 8+ default int anotherMethod() { return 1; } } class C implements A, B { // se as interfaces tiverem // implementações default // de métodos com a mesma assinatura // é obrigatório redefiní-lo na classe }

C#

interface IA { // método estático static public int someStaticMethod() { return 1; } // método virtual int someMethod(); } interface IB { // método virtual int someOtherMethod(); // método default // c# 8+ int anotherMethod() { return 1; } // TODO interfaces agora podem // ter métodos e pripriedades // private, protected, etc... } class C : IA, IB { // se as interfaces tiverem // implementações default // de métodos com a mesma assinatura // é obrigatório redefiní-lo na classe }

Dart

TypeScript

JavaScript

-

ActionScript

Python

-

PHP

VBA / VB6 IA.cls

[File: IA.cls, Instancing: PublicNotCreatable] Option Explicit Public Property Get Name() As String End Property

VBA / VB6 - C.cls

[File: C.cls, Instancing: Private] Option Explicit Implements IA Private m_name As String Private Sub Class_Initialize() m_name = "" End Sub Public Property Get Name() As String Name = m_name End Property

VBA / VB6 - Module.bas

[File: Module1.bas] Option Explicit Public Sub TestInterface() Dim someObject As New C someObject.Name = "John" End Sub

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Herança

Rust

trait Foo { fn foo(&self); } trait Bar { fn bar(&self); } trait FooBar : Foo + Bar { fn foobar(&self); }

Go

// não suporta herança, // mas tem um atalho para composição

C++

class A { // } class B : A { // } class C : A { // } // herança múltipla // usar herança virtual para diminuir // problemas com ambiguidade class D final : B, C { // super }

Objective-C

@interface A : NSObject // @end @interface B : A // super @end

Swift

class C { static func myStaticMethod() { // } static var myStaticProp:S init() { // } deinit { // } private func myMethod() { self.prop } var getter:S { return ... } var getterSetter:S { get { return self._getterSetter } set(newValue) { // ou newValue implícito set { self._getterSetter = newValue } } lazy var prop:S private _getterSetter:S // setter pode ser menos visível que o getter public private(set) var numberOfEdits = 0 // internal private(set) var numberOfEdits = 0 } final class R : C { required init() { // super } } let o1 = C() let o2 = D()

Kotlin

open class A() { // } class B() : A() { // super }

Java

class A { // } final class B extends A { // super } sealed class C permits D { // } final class D extends C { // }

C#

class A { // } sealed class B : A { // base }

Dart

TypeScript

JavaScript

class A { // } class B extends A { constructor() { super(); // TODO verificar Object.seal(this); } } // ou let a = {}; let b = Object.create(a, {});

ActionScript

Python

class A: class B(A): class C(A): # herança múltipla # veja C3 para resolução # de métodos com mesma assinatura class D(B, C): pass # super()

PHP

VBA / VB6

-

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Classes abstratas

Rust

-

Go

-

C++

class AbstractClass { // virtual e =0 fazem essa função ser puramente virtual // o que torna a classe abstrata virtual void AbstractMemberFunction() = 0; // uma classe abstrata ainda pode conter outros tipos de métodos // e atributos virtual void NonAbstractMemberFunction1(); // Virtual function. void NonAbstractMemberFunction2(); };

Objective-C

-

Swift

-

Kotlin

abstract class A { // } // uma classe abstrata pode ser inserida // no meio de uma cadeia de herança open class B { open fun someMethod() {} } abstract class C : B() { abstract override fun someMethod() }

Java

abstract class A { // }

C#

abstract class A { // }

Dart

TypeScript

JavaScript

-

ActionScript

Python

from abc import ABC class AbstractBaseClass(ABC): pass # ou class AbstractBaseClass(ABC): @abstractmethod def my_abstract_method(self, ...): # @property @abstractmethod def my_abstract_property(self): #

PHP

VBA / VB6

-

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

LLVM IR

  1. a

A

Classes Anônimas

Rust

-

Go

-

C++

-

Objective-C

-

Swift

-

Kotlin

public final class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState:Bundle?) { super.onCreate(savedInstanceState) this.txtValorMes!!.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s:CharSequence, start:Int, count:Int, after:Int) { /**/} override fun onTextChanged(s:CharSequence, start:Int, before:Int, count:Int) { // this@ acessa o escopo nomeado this@MainActivity.mainProperty } override fun afterTextChanged(s:Editable) { /**/ } }) } private var mainProperty:Int }

Java

public final class MainActivity extends AppCompatActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState) this.txtValorMes.addTextChangedListener(new TextWatcher { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { /**/ } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // Container.this acessa o escopo externo Container.this.mainProperty; } @Override public void afterTextChanged(Editable s) { /**/ } }) } private int mainProperty; }

C#

// C# tem anonymus types // que só podem ter atributos e nada mais

Dart

TypeScript

JavaScript

// JavaScript não tem classes // apenas objetos // Objetos anônimos podem // ser criados facilmente // com a sintaxe {}

ActionScript

Python

# ver https://docs.python.org/3/library/types.html

PHP

VBA / VB6

-

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

  1. a

A

Resolução de tipos

Rust

// ver "trait objects" na doc oficial

Go

C++

Objective-C

// dynamic dispatch

Swift

// static e dynamic dispatch

Kotlin

Java

C#

Dart

TypeScript

JavaScript

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

  1. a

A

Tipo Genérico

Rust

pub struct Generica<T> { // valor padrão para T é Default::default() propriedadeGenerica: T }

Go

-

C++

template <class T> class Generica final { T propriedadeGenerica; }

Objective-C

@interface Generica<__covariant ObjectType> : NSObject @property (assign, nonatomic) ObjectType propriedadGenerica; @end @interface HerdaDeU<__covariant ObjectType:U *> : NSObject @end // TODO __contravariant tb pode ser usado? // usa type erasure :(

Swift

public final class Generica<T> { // TODO qual é o valor padrão de T? private T propriedadeGenerica// = [Element]() } public final class Generica2Tipos<T, U> { // } public final class HerdaDeU<T : U> { // } public final class Restricoes<T : U> where T.Item == U.Item { // }

Kotlin

public class Generica<T>() { // } // TODO ver where, in e out // usa type erasure :(

Java

public final class Generica<T> { // valor padrão para T é null private T propriedadeGenerica = null; } Generica gen1 = new Generica<Integer>(); public final class Generica2Tipos<T, U> { // } Generica2Tipos gen2 = new Generica2Tipos<Integer, Float>(); public final class HerdaDeU<T extends U> { // } public final class RegrasCombinadas<T extends U & V> { // } public final class Coringa<?> { // ou wildcard, permite qquer coisa } public final class CoringaTipado<? extends Number> { // pois Generica<Integer> não herda de Generica<Number> // mas o wild card CoringaTipado<? extends Number> // permite CoringaTipado<Integer> } // usa type erasure, permitindo bugs com casts etc.

C#

public sealed class Generica<T> { // valor padrão para T é default(T) private T propriedadeGenerica = default(T); } var gen1 = new Generica<int>(); public sealed class Generica2Tipos<T, U> { // } var gen2 = new Generica2Tipos<int, float>(); public sealed class SoValueType<T> where T : struct { // } var gen3 = new SoValueType<int>(); public sealed class SoReferenceType<T> where T : class { // } var gen4 = new SoReferenceType<object>(); public sealed class PossuiConstrutorPublicoPadrao<T> where T : new() { // } public sealed class HerdaDeU<T> where T : U { // } public sealed class RegrasCombinadas<T> where T : U, V, new() { // }

Dart

TypeScript

JavaScript

// tipagem dinâmica

ActionScript

Python

from typing import TypeVar, Generic T = TypeVar('T') S = TypeVar('S', int, str) class StrangePair(Generic[T, S]): # from typing import TypeVar, Generic from logging import Logger T = TypeVar('T') class LoggedVar(Generic[T]): def __init__(self, value: T, name: str, logger: Logger) -> None: self.name = name self.logger = logger self.value = value def set(self, new: T) -> None: self.log('Set ' + repr(self.value)) self.value = new def get(self) -> T: self.log('Get ' + repr(self.value)) return self.value def log(self, message: str) -> None: self.logger.info('%s: %s', self.name, message)

PHP

VBA / VB6

-

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

  1. a

A

Operator Overload

Rust - main.rs

mod MusicNote; mod Enumerators; use Enumerators::Step; use Enumerators::Semitone; fn main() { let mut musicNote = MusicNote::MusicNote { step: Step::Do, semitone: Default::default() }; musicNote = musicNote + Semitone::Sharp; println!("{}", musicNote); // Do♯ }

Rust - MusicNote.rs

use std::ops::Add; use std::fmt; use Enumerators::Step; use Enumerators::Semitone; pub struct MusicNote { /*pub Step Step { get; private set; } pub Semitone Semitone { get; set; }*/ pub step:Step, pub semitone:Semitone } impl Add<Semitone> for MusicNote { type Output = MusicNote; fn add(self, rightHandSide:Semitone) -> MusicNote { if rightHandSide == Semitone::None { return self; } let mut newStep = self.step; let mut newSemitone = rightHandSide; if newSemitone == Semitone::Sharp && (newStep == Step::Mi || newStep == Step::E) { newStep = Step::Fa; newSemitone = Semitone::None; } else if newSemitone == Semitone::Flat && (newStep == Step::Fa || newStep == Step::F) { newStep = Step::Mi; newSemitone = Semitone::None; } // Rest of add logic here return MusicNote { step: newStep, semitone: newSemitone } } } impl fmt::Display for MusicNote { fn fmt(&self, formatter:&mut fmt::Formatter) -> fmt::Result { write!(formatter, "{}{}", self.step, self.semitone) } }

Rust - Enumerators.rs

use std::default::Default; use std::fmt; // Rust não permite que uma mesma literal // seja atribuído a dois valores diferentes // Do = 1, C = 1 #[derive(PartialEq, Eq)] pub enum Step { // solfèje Do, Re, Mi, Fa, Sol, La, Si, // abc C, D, E, F, G, A, B } impl fmt::Display for Step { fn fmt(&self, formatter:&mut fmt::Formatter) -> fmt::Result { match *self { Step::Do | Step::C => write!(formatter, "Do"), Step::Re | Step::D => write!(formatter, "Re"), Step::Mi | Step::E => write!(formatter, "Mi"), Step::Fa | Step::F => write!(formatter, "Fa"), Step::Sol | Step::G => write!(formatter, "Sol"), Step::La | Step::A => write!(formatter, "La"), Step::Si | Step::B => write!(formatter, "Si") } } } #[derive(PartialEq, Eq)] pub enum Semitone { None = 127, Natural = 0, DoubleFlat = -2, Flat = -1, Sharp = 1, DoubleSharp = 2 } impl Default for Semitone { fn default() -> Semitone { Semitone::None } } impl fmt::Display for Semitone { fn fmt(&self, formatter:&mut fmt::Formatter) -> fmt::Result { match *self { Semitone::None => write!(formatter, ""), Semitone::Natural => write!(formatter, "♮"), Semitone::DoubleFlat => write!(formatter, "𝄫"), Semitone::Flat => write!(formatter, "♭"), Semitone::Sharp => write!(formatter, "♯"), Semitone::DoubleSharp => write!(formatter, "𝄪") } } }

Go

-

C++ - main.cpp

#include <iostream> #include "MusicNote.hpp" int main(int argc, const char* argv[]) { using std::cout; using std::endl; using MarcoLuglio::OpOvExample::MusicNote; using MarcoLuglio::OpOvExample::Step; using MarcoLuglio::OpOvExample::Semitone; auto cSharp = MusicNote(Step::C, Semitone::None); cSharp = cSharp + Semitone::Sharp; cout << cSharp << endl; // Do♯ auto note1 = MusicNote(Step::C); cout << note1++ << endl; // Do auto note2 = MusicNote(Step::C); cout << ++note2 << endl; // Do♯ return 0; }

C++ - MusicNote.hpp

#pragma once #include <cstdint> #include <string> #include "Enumerators.hpp" namespace MarcoLuglio { namespace ThreadExample { class MusicNote final { public: MusicNote(Step step, Semitone semitone = Semitone::None); // Não é possível declarar operator<< como // um membro da classe. Mas podemos declará-lo // como uma friend function, que consegue acessar // as propriedades privadas da classe como se // fosse um membro friend std::ostream& operator<<( std::ostream& os, const MusicNote& obj ); MusicNote operator+(const Semitone semitone) const; /// prefix increment MusicNote& operator++(); /// postfix increment MusicNote operator++(int); Step getStep(); Semitone getSemitone(); private: Step step; Semitone semitone; }; } }

C++ - MusicNote.cpp

#include "MusicNote.hpp" namespace MarcoLuglio { namespace ThreadExample { using std::string; MusicNote::MusicNote(Step step, Semitone semitone) : step{step}, semitone{semitone} { // } MusicNote MusicNote::operator+(const Semitone semitone) const { if (semitone == Semitone::None) { return *this; } Step newStep = this->step; Semitone newSemitone = semitone; if (newSemitone == Semitone::Sharp && (newStep == Step::Mi || newStep == Step::E) ) { newStep = Step::Fa; newSemitone = Semitone::None; } else if (newSemitone == Semitone::Flat && (newStep == Step::Fa || newStep == Step::F) ) { newStep = Step::Mi; newSemitone = Semitone::None; } // Rest of add logic here return MusicNote(newStep, newSemitone); } MusicNote& MusicNote::operator++() { MusicNote& ref = *this; auto tmp = ref + Semitone::Sharp; this->step = tmp.getStep(); this->semitone = tmp.getSemitone(); return ref; } MusicNote MusicNote::operator++(int) { MusicNote tmp{*this}; // copy this->operator++(); // pre-increment return tmp; // return old value } Step MusicNote::getStep() { return this->step; } Semitone MusicNote::getSemitone() { return this->semitone; } std::ostream& operator<<( std::ostream& os, const MusicNote& note ) { os << note.step << note.semitone; return os; } } }

C++ - Enumerators.hpp

#pragma once namespace MarcoLuglio { namespace OpOvExample { enum Step : uint8_t { // solfèje Do = 1, Re = 3, Mi = 5, Fa = 6, Sol = 8, La = 10, Si = 12, // abc C = 1, D = 3, E = 5, F = 6, G = 8, A = 10, B = 12 }; enum Semitone : int8_t { None = 127, Natural = 0, DoubleFlat = -2, Flat = -1, Sharp = 1, DoubleSharp = 2 }; std::ostream& operator<<(std::ostream& os, const Step& step); std::ostream& operator<<(std::ostream& os, const Semitone& semitone); } }

C++ - Enumerators.cpp

#include "Enumerators.hpp" namespace MarcoLuglio { namespace OpOvExample { std::ostream& operator<<( std::ostream& os, const Step& step ) { switch (step) { case Step::Do: os << "Do"; break; case Step::Re: os << "Re"; break; case Step::Mi: os << "Mi"; break; case Step::Fa: os << "Fa"; break; case Step::Sol: os << "Sol"; break; case Step::La: os << "La"; break; case Step::Si: os << "Si"; break; default: break; } return os; } std::ostream& operator<<( std::ostream& os, const Semitone& semitone ) { switch (semitone) { case Semitone::None: break; case Semitone::Natural: os << "♮"; break; case Semitone::DoubleFlat: os << "𝄫"; break; case Semitone::Flat: os << "♭"; break; case Semitone::Sharp: os << "♯"; break; case Semitone::DoubleSharp: os << "𝄪"; break; default: break; } return os; } } }

Objective-C

-

Swift - main.swift

var musicNote = MusicNote(step: Step.do, semitone: Semitone.none) musicNote = musicNote + Semitone.sharp print(musicNote) // Do♯

Swift - MusicNote.swift

public final class MusicNote : CustomStringConvertible { init(step:Step, semitone:Semitone = Semitone.none) { self.step = step self.semitone = semitone } public var description:String { return "\(self.step)\(self.semitone)" } public fileprivate(set) var step = Step.do public var semitone = Semitone.none } // posso fazer isso estático tb dentro da classe MusicNote func + (left:MusicNote, right:Semitone) -> MusicNote { if right == Semitone.none { return left } var newStep:Step = left.step var newSemitone:Semitone = right if newSemitone == Semitone.sharp && (newStep == Step.mi || newStep == Step.e) { newStep = Step.fa newSemitone = Semitone.none } else if newSemitone == Semitone.flat && (newStep == Step.fa || newStep == Step.f) { newStep = Step.mi; newSemitone = Semitone.none; } // Rest of add logic here return MusicNote(step: newStep, semitone: newSemitone) }

Swift - Enumerators.swift

// Rust não permite que uma mesma literal // seja atribuído a dois valores diferentes // `do` = 1, c = 1 public enum Step : UInt8, CustomStringConvertible { // solfèje case `do` case re case mi case fa case sol case la case si // abc case c case d case e case f case g case a case b public var description:String { switch self { case .do, .c: return "Do" case .re, .d: return "Reo" case .mi, .e: return "Mi" case .fa, .f: return "Fa" case .sol, .g: return "Sol" case .la, .a: return "La" case .si, .b: return "Si" } } } public enum Semitone : Int8, CustomStringConvertible { case none = 127 case natural = 0 case doubleFlat = -2 case flat = -1 case sharp = 1 case doubleSharp = 2 public var description:String { switch self { case .none: return "" case .natural: return "♮" case .doubleFlat: return "𝄫" case .flat: return "♭" case .sharp: return "♯" case .doubleSharp: return "𝄪" } } }

Kotlin - main.kt

fun main(args: Array<String>) { // }

Kotlin - MusicNote.kt

public final class MusicNote { // } operator fun MusicNote.inc():MusicNote { // } operator fun MusicNote.plus(semitone:Semitone) { // }

Kotlin - Semitone.kt

Java

-

C# - MainClass.cs

using System; namespace MarcoLuglio.OpOvExample { public class MainClass { public static void Main(string[] args) { // Sim, de onde você achava que tinha vindo?? var cSharp = new MusicNote(Step.C, Semitone.None); cSharp = cSharp + Semitone.Sharp; Console.WriteLine(cSharp); // Do♯ var note1 = new MusicNote(Step.C); Console.WriteLine(note1++); // Do var note2 = new MusicNote(Step.C); Console.WriteLine(++note2); // Do♯ } } }

C# - MusicNote.cs

using System; namespace MarcoLuglio.OpOvExample { public sealed class MusicNote { public static MusicNote operator +(MusicNote note, Semitone semitone) { if (semitone == Semitone.None) { return note; } Step newStep = note.step; Semitone newSemitone = semitone; if (newSemitone == Semitone.Sharp && (newStep == Step.Mi || newStep == Step.E) ) { newStep = Step.Fa; newSemitone = Semitone.None; } else if (newSemitone == Semitone.Flat && (newStep == Step.Fa || newStep == Step.F) ) { newStep = Step.Mi; newSemitone = Semitone.None; } // Rest of add logic here return new MusicNote(newStep, newSemitone); } public static MusicNote operator ++(MusicNote note) { // Retorne sempre um novo objeto dentro desse override // Para que que o prefixo e o sufixo ++ funcionem corretamente // Nesse caso o override do + irá se encarregar disso return note + Semitone.Sharp; } public MusicNote(Step step, Semitone semitone = Semitone.None) { this.Step = step; this.Semitone = semitone; } public override string ToString() { return string.Format("{0}{1}", Step, Semitone.ToDescriptionString()); } public Step Step { get; private set; } public Semitone Semitone { get; set; } private Step step = Step.Do; private Semitone semitone = Semitone.None; } }

C# - Enumerators.cs

using System; using System.ComponentModel; // Description attribute namespace MarcoLuglio.OpOvExample { public enum Step : byte { // solfèje Do = 1, Re = 3, Mi = 5, Fa = 6, Sol = 8, La = 10, Si = 12, // abc C = 1, D = 3, E = 5, F = 6, G = 8, A = 10, B = 12 } public enum Semitone : sbyte { [Description("")] None = 0, [Description("♮")] Natural = 0, [Description("\uD834\uDD2B")] DoubleFlat = -2, [Description("♭")] Flat = -1, [Description("♯")] Sharp = 1, [Description("\uD834\uDD2A")] DoubleSharp = 2 } public static class SemitoneExtensions { public static string ToDescriptionString(this Semitone semitone) { DescriptionAttribute[] attributes = (DescriptionAttribute[])semitone .GetType() .GetField(semitone.ToString()) .GetCustomAttributes(typeof(DescriptionAttribute), false); return attributes.Length > 0 ? attributes[0].Description : string.Empty; } } }

Dart

// https://dart.dev/guides/language/language-tour#methods

TypeScript

-

JavaScript

// https://github.com/tc39/proposal-operator-overloading

ActionScript

Python - main.py

#

Python - MusicNote.py

class MusicNote: #

Python - Semitone.py

from enum import Enum class Color(Enum): RED = 1 GREEN = 2 BLUE = 3

VBA / VB6

-

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

  1. a

A

Indexing Coleções de Objetos como Arrays

Rust - OpOvCollection.rs

use std::ops::Index; use std::ops::IndexMut; use std::default::Default; pub struct OpOvCollection<T> where T:Default { pub array:[T; 10] } // pode ser indexada por inteiros impl<T> Index<usize> for OpOvCollection<T> where T:Default { type Output = T; fn index(&self, index:usize) -> &T { &self.array[index] } } // pode ser indexada por inteiros impl<T> IndexMut<usize> for OpOvCollection<T> where T:Default { fn index_mut<'a>(&'a mut self, index:usize) -> &'a mut T { &mut self.array[index] } } // ou por outros tipos // TODO impl<T> Default for OpOvCollection<T> where T:Default { fn default() -> OpOvCollection<T> { OpOvCollection::<T> { array: Default::default() } } }

Rust - main.rs

let mut opOvCollection:OpOvCollection::OpOvCollection<str> = Default::default(); opOvCollection[0] = "sunday"; opOvCollection[1] = "monday I'm in love"; opOvCollection[2] = "tuesday and wednesday too"; println!("{}", opOvCollection[2]);

Go

-

C++ - OpOvCollection.hpp

#pragma once #include <string> namespace MarcoLuglio { namespace IndexerExample { using std::size_t; using std::string; using std::to_string; /// type alias para simplificar a sintaxe /// do retorno da função getArray using arrayReference = int[10]; class OpOvCollection final { public: /// Classe auxiliar que permite alteração /// dos valores da coleção class Proxy final { public: Proxy(OpOvCollection& collection, const size_t index) : collection{collection}, index{index} {} /// Overload do operador = para alteração /// dos valores da coleção int& operator= (int newValue) { collection.array[index] = newValue; return collection.array[index]; // FIXME } /// C++ não possui uma classe base comum /// então as conversões para string devem ser /// implementadas sempre operator string() const { return to_string(collection.array[index]); } private: /// Referência da coleção original, para alteracão /// dos valores nos índices OpOvCollection &collection; size_t index; }; OpOvCollection(); /// Overload do operador [] para obtenção /// dos valores da coleção /// Esse overload só possibilita retornar valores, /// portanto é necessário que ele retorne um objeto /// proxy ao invés do valor real, pois o proxy /// possibilita a alteração do valor na coleção /// original OpOvCollection::Proxy operator[](const size_t index); private: /// Coleção original int array[10]; } } }

C++ - OpOvCollection.cpp

#include "OpOvCollection.hpp" namespace MarcoLuglio { namespace IndexerExample { using CollectionProxy = OpOvCollection::Proxy; using std::size_t; /// type alias para simplificar a sintaxe /// do retorno da função getArray using arrayReference = int[10]; OpOvCollection::OpOvCollection() { // inicia a array com valores 0 std::fill(this->array, this->array + 9, 0); } CollectionProxy OpOvCollection::operator[](const size_t index) { return CollectionProxy(*this, index); } } }

C++ - main.cpp

#include <iostream> #include <string> #include "OpOvCollection.hpp" int main(int argc, const char* argv[]) { using std::cout; using std::endl; using std::string; using MarcoLuglio::IndexerExample::OpOvCollection; auto opOvCollection = OpOvCollection(); opOvCollection[0] = 7; opOvCollection[1] = 45; opOvCollection[2] = 83; string value = (string)opOvCollection[2]; // 83 cout << value << endl; return 0; }

Objective-C - IndexedCollection.h

@interface { } // pode ser indexada por inteiros - (id) objectAtIndexedSubscript:(int)index; - (void) setObject:(id)obj atIndexedSubscript:(int)index; // ou por outros tipos - (id) objectForKeyedSubscript:(NSString)key; - (void) setObject:(id)obj forKeyedSubscript:(NSString)key; @end

Objective-C - IndexedCollection.m

#import "IndexedCollection.h" @implementation // TODO @end

Objective-C - main.m

#import "IndexedCollection.h" int main(int argc, const char* argv[]) { IndexedCollection* indexedCollection = [IndexedCollection new]; indexedCollection[0] = "sunday"; indexedCollection[1] = "monday I'm in love"; indexedCollection[2] = "tuesday and wednesday too"; // "tuesday and wednesday too" NSLog(indexedCollection["tuesday"]); return 0; }

Swift - SubscriptCollection.swift

// Swift não tem valores padrão para tipos, nem tem uma classe base comum // Então usamos um protocolo que o tipo genérico deve seguir public final class SubscriptCollection<T:StringLiteralConvertible> { init() { self.array = [T](count:10, repeatedValue:"") } // pode ser indexada por inteiros subscript(index:Int) -> T { get { return self.array[index] } set(newValue) { self.array[index] = newValue } } // ou por outros tipos subscript(key:String) -> T { get { var string:String var stringStart:String var stringIndex:String.Index for item in self.array { string = String(item) if string.isEmpty || string == "nil" { continue } stringIndex = string.startIndex.advancedBy(key.count) stringStart = string.substringToIndex(stringIndex) if stringStart == key { return item } } // retorna uma string vazia se não encontrar um item pela chave // já que o tipo deve poder ser convertido para string return "" } } // e ainda por mais de um índice subscript(key:String, index:Int) -> T { get { var string:String var stringStart:String var stringIndex:String.Index var currentIndex = 0 for item in self.array { string = String(item) if string.isEmpty || string == "nil" { continue } stringIndex = string.startIndex.advancedBy(key.count) stringStart = string.substringToIndex(stringIndex) if stringStart == key { if currentIndex == index { return item } else { currentIndex = currentIndex + 1 } } } return "" } } var array:Array<T> }

Swift - main.swift

var subscriptCollection = SubscriptCollection<String>() subscriptCollection[0] = "sundays are slow"; subscriptCollection[1] = "mondays are mediocre"; subscriptCollection[2] = "tuesday and wednesday too"; subscriptCollection[3] = "monday again"; // "tuesday and wednesday too" print(subscriptCollection["tuesday"]); // "monday again" print(subscriptCollection["monday", 1]);

Kotlin - IndexedCollection.kt

class Point(val x:Int, val y:Int) operator fun Point.get(i) = Point(-x, -y) val point = Point(10, 20) fun main() { println(-point) // prints "Point(x=-10, y=-20)" } // TODO implementar operador get conforme abaixo /* a[i] a.get(i) a[i, j] a.get(i, j) a[i_1, ..., i_n] a.get(i_1, ..., i_n) a[i] = b a.set(i, b) a[i, j] = b a.set(i, j, b) a[i_1, ..., i_n] = b a.set(i_1, ..., i_n, b) */

Kotlin - main.kt

Java

-

C# - IndexedCollection.cs

namespace MarcoLuglio.IndexerExample { public sealed class IndexedCollection<T> { public IndexedCollection() { this.array = new T[10]; } // pode ser indexada por inteiros public T this[int index] { get { return this.array [index]; } set { this.array [index] = value; } } // ou por outros tipos public T this[string key] { get { foreach(var item in this.array) { if (item.ToString().StartsWith(key)) { return item; } } // retorna valor padrão para o tipo // se não encontrar um item pela chave return default(T); } } private T[] array; } }

C# - MainClass.cs

using System; namespace MarcoLuglio.IndexerExample { public class MainClass { public static void Main(string[] args) { var indexedCollection = new IndexedCollection<string>(); indexedCollection[0] = @"sunday"; indexedCollection[1] = @"monday I'm in love"; indexedCollection[2] = @"tuesday and wednesday too"; // "tuesday and wednesday too" Console.WriteLine(indexedCollection[@"tuesday"]); } } }

Dart

class Test { Map data = { "a": 1, "b": 2 }; operator [](index) => data[index]; operator []=(index, value) { data[index] = value; } }

TypeScript

JavaScript

'use strict'; const indexingProxy = { get(alvo, propriedade, receiver) { // pode ser indexada por inteiros if (/^\d+$/.test(propriedade)) { return Reflect.get(alvo._array, propriedade, receiver); } // ou por outros tipos for (let valor of alvo._array) { if (valor.startsWith(propriedade)) { return valor; } } // retorna null // se não encontrar um item pela chave return null; }, set(alvo, propriedade, valor, receiver) { // pode ser indexada por inteiros if (/^\d+$/.test(propriedade)) { alvo._array[propriedade] = valor; return true; } // ou por outros tipos alvo._array.push(valor); return true; } }; class Collection { constructor() { Object.defineProperty(this, '_array', {value: []}); } } const collection = new Collection(); const indexedCollection = new Proxy(collection, indexingProxy); indexedCollection[0] = "sunday"; indexedCollection[1] = "monday I'm in love"; indexedCollection[2] = "tuesday and wednesday too"; // "tuesday and wednesday too" console.log(indexedCollection["tuesday"]);

ActionScript

Python

# implementar object.__getitem__(self, key)

PHP

VBA / VB6

-

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

  1. C# / Swift
  2. JavaScript
  3. C++

C# possibilita a criação de indexers de maneira relativamente simples. Swift requer passos extras devido ao fato de que não existe uma maneira rápida de obter o valor padrão de um tipo genérico, mas isso é compensado pelo fato de que é simples utilizar mais de um índice com o operador [].
JavaScript não diferencia os operadores . e [], mas se os utilizarmos ingenuamente, deixaremos o código lento, criando propriedades nos objetos em tempo de execução. Por isso o uso de um Proxy se faz necessário.
C++ Também requer um proxy, mas por outros motivos. O operador [] em C++ só retorna valores, então devemos retornar um proxy que possui uma referência para a posição desejada na coleção original, e por meio dele alterar o valor nessa posição. Para que isso seja possível, o proxy também deve ter alguns overloads de operadores, tornando tudo mais verborrágico e complicado do que nas outras linguagens.

Meta dados (annotations / attributes / decorators)

Rust

// use procedural macros // TODO #[proc_macro_attribute] pub fn show_streams( attr: TokenStream, item: TokenStream ) -> TokenStream { println!("attr: \"{}\"", attr.to_string()); println!("item: \"{}\"", item.to_string()); item } #[show_streams(bar)] fn invoke2() {}

Go

package main import ( "fmt" "reflect" ) type T struct { f1 string "f one" f2 string f3 string `f three` f4, f5 int64 `f four and five` f6 string `one:"1" two:"2"blank:""` } func main() { t := reflect.TypeOf(T{}) f1, _ := t.FieldByName("f1") fmt.Println(f1.Tag) // f one f4, _ := t.FieldByName("f4") fmt.Println(f4.Tag) // f four and five f5, _ := t.FieldByName("f5") fmt.Println(f5.Tag) // f four and five f6, _ := t.FieldByName("f6") fmt.Println(f6.Tag) // one:"1" two:"2"blank:"" v, ok := f6.Tag.Lookup("one") fmt.Printf("%s, %t\n", v, ok) // 1, true v, ok = f6.Tag.Lookup("blank") fmt.Printf("%s, %t\n", v, ok) // , true v, ok = f6.Tag.Lookup("five") fmt.Printf("%s, %t\n", v, ok) // , false }

C++

-

Objective-C

// não permite atributos customizados // apenas pré-definidos

Swift

// não permite atributos customizados // apenas pré-definidos

Kotlin

@Target(AnnotationTarget.CLASS) annotation class AClassAnnotation(val aParam:String) @Target(AnnotationTarget.FUNCTION) annotation class AMethodAnnotation(val aParam:String) @AClassAnnotation("metadata about class") class AnnotatedClass { @AMethodAnnotation("metadata about class") void AnnotatedMethod() { // } } val aClassAnnotation = AnnotatedClass::class .annotations .find { it is AClassAnnotation } as? AClassAnnotation println(AClassAnnotation?.aParam)

Java

@Target(ElementType.CLASS) @Retention(RetentionPolicy.RUNTIME) public @interface AClassAnnotation { public String aParam() default ""; } @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AMethodAnnotation { public String aParam() default ""; } @AClassAnnotation(aParam = "metadata about class") class AnnotatedClass { @AMethodAnnotation(aParam = "metadata about class") void AnnotatedMethod() { // } } AClassAnnotation aClassAnnotation = obj .getClass() .getAnnotation(AClassAnnotation.class); if (aClassAnnotation != null) { String aParam = aClassAnnotation.aParam(); }

C#

[AttributeUsage(AttributeTargets.Class, Inherited = false)] public class AClassAttribute : Attribute { public AClassAttribute(string aParam) { // } } [AttributeUsage(AttributeTargets.Method, Inherited = false)] public class AMethodAttribute : Attribute { public AMethodAttribute(string aParam) { // } } [AClassAttribute("metadata about class")] public sealed class AnnotatedClass { [AMethodAttribute("metadata about method")] public void AnnotatedMethod() { ... } } var annotatedClassType = typeof(AnnotatedClass); var aClassAttribute = (AClassAttribute) Attribute.GetCustomAttribute( annotatedClassType, typeof (AClassAttribute) );

Dart

class AnAnnotation { final String name; final String description; const Todo(this.name, this.description); } @AnAnnotation('Chibi', 'Rename class') class AnnotatedClass { @AnAnnotation('Tuwaise', 'Change fielld type') int annotatedValue; } AnnotatedClass annotatedClass = new AnnotatedClass(); InstanceMirror im = reflect(annotatedClass); ClassMirror classMirror = im.type; classMirror.metadata.forEach((metadata) { if (metadata.reflectee is Todo) { print(metadata.reflectee.name); print(metadata.reflectee.description); } }); for (var v in classMirror.declarations.values) { if (!v.metadata.isEmpty) { if (v.metadata.first.reflectee is Todo) { print(v.metadata.first.reflectee.name); print(v.metadata.first.reflectee.description); } } }

TypeScript

JavaScript

// acompanhe essa feature

ActionScript

package { import flash.display.Sprite; // pure .as file projects accepted metadata for the stage settings [SWF(width="1024", height="768", backgroundColor='#405050', frameRate="60")] public class MainStage extends Sprite { public function MainStage() { stage.quality = StageQuality.HIGH; stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; super(); } } }

Python

def a_class_decorator(cls): class NewClass(cls): attr = 100 return NewClass @a_class_decorator class X: pass def a_function_decorator(aParam, func): def wrapper(): print("Do something") func() return wrapper @a_function_decorator("a param") def say_whee(): print("Whee!") ##################################### import functools class state_decorator: def __init__(self, func): functools.update_wrapper(self, func) self.func = func self.num_calls = 0 def __call__(self, *args, **kwargs): self.num_calls += 1 print(f"Call {self.num_calls} of {self.func.__name__!r}") return self.func(*args, **kwargs) @state_decorator def say_whee(): print("Whee!")

PHP

VBA / VB6

-

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

LLVM IR

  1. a

A

Interface Binária C Foreign Function Interface

Exportar para C

Rust - TabelaNutricional.rs

#[repr(C)] pub struct TabelaNutricional { valorEnergetico:f32, carboidratos:f32, proteinas:f32, gordurasTotais:f32, gordurasSaturadas:f32, gordurasTrans:f32, fibraAlimentar:f32, sodio:f32 } #[no_mangle] pub extern "C" fn calcular(porcao:f32) -> TabelaNutricional { let mut tabela = TabelaNutricional{ valorEnergetico: 1_f32, carboidratos: 1_f32, proteinas: 1_f32, gordurasTotais: 1_f32, gordurasSaturadas: 1_f32, gordurasTrans: 1_f32, fibraAlimentar: 1_f32, sodio: 2_f32 }; // TODO usar porcao return tabela; } // compilar com // rustc --crate-type dylib TabelaNutricional.rs // vai gerar libTabelaNutricional.dylib /* Calling conventons válidas: stdcall aapcs cdecl fastcall Rust rust-intrinsic system C win64 sysv64 */

Go

// compile using -buildmode=c-shared // go build -o nutricao.so -buildmode=c-shared nutricao.go

C++ - TabelaNutricional.hpp

#pragma once #ifdef __cplusplus namespace MarcoLuglio { namespace FFIExample { extern "C" { #endif struct TabelaNutricional { float valorEnergetico; float carboidratos; float proteinas; float gordurasTotais; float gordurasSaturadas; float gordurasTrans; float fibraAlimentar; float sodio; }; #ifdef __cplusplus } } } #endif

C++ - TabelaNutricional.cpp

#include "TabelaNutricional.hpp" namespace MarcoLuglio { namespace FFIExample { // TODO ver se esse arquivo // é realmente necessário } }

C++ - TabelaNutricionalBiblioteca.hpp

#pragma once #ifdef _MSC_VER // Visual Studio specific macro #define DLLEXPORT __declspec(dllexport) #else #define DLLEXPORT __attribute__((visibility("default"))) #endif #include "TabelaNutricional.hpp" #ifdef __cplusplus namespace MarcoLuglio { namespace FFIExample { extern "C" { #endif DLLEXPORT struct TabelaNutricional calcular(float porcao); #ifdef __cplusplus } } } #endif

C++ - TabelaNutricionalBibliteca.cpp

#include "TabelaNutricional.hpp" #include "TabelaNutricionalBibliteca.hpp" namespace MarcoLuglio { namespace FFIExample { TabelaNutricional calcular(const float porcao) { TabelaNutricional tabela{}; // ... return tabela; } } }

Objective-C

-

Swift

-

Kotlin

-

Java

-

C#

-

Dart

-

TypeScript

-

JavaScript

-

ActionScript

-

Python

-

PHP

-

VBA / VB6

' ??

Ada - Nutricao.ads

-- usar pragma Convention e Export with Interfaces.C; package Nutricao is type TabelaNutricional is record ValorEnergetico:Interfaces.C.C_float; Carboidratos:Interfaces.C.C_float; Proteinas:Interfaces.C.C_float; GordurasTotais:Interfaces.C.C_float; GordurasSaturadas:Interfaces.C.C_float; GordurasTrans:Interfaces.C.C_float; FibraAlimentar:Interfaces.C.C_float; Sodio:Interfaces.C.C_float; end record; pragma Convention ( Convention => C, Entity => TabelaNutricional ); function Calcular(Porcao:Float) return TabelaNutricional; pragma Export (C, Calcular, "calcular"); end Nutricao;

Nutricao.adb

package body Nutricao is function Calcular(Porcao:Float) return TabelaNutricional is begin -- return ...; end Calcular; end Nutricao;

Object Pascal (Delphi)

type TObj = object private Caption:ShortString; public constructor init; destructor done; procedure SetCaption(AValue:String); function GetCaption:String; end; type point = record X,Y,Z:Real; end; type RPoint = record case Boolean of False: (X,Y,Z:Real); True: (R,theta,phi:Real); end; type BetterRPoint = record case UsePolar:Boolean of False: (X,Y,Z:Real); True: (R,theta,phi:Real); end; function Calcular(Porcao:Single):TabelaNutricional; cdecl; begin // return ...; end; { Calling conventons válidas: register pascal cdecl stdcall safecall winapi }

Ruby

Smalltalk

Common Lisp

Haskell

Importar do C

Rust

#[repr(C)] pub struct TabelaNutricional { valorEnergetico:f32, carboidratos:f32, proteinas:f32, gordurasTotais:f32, gordurasSaturadas:f32, gordurasTrans:f32, fibraAlimentar:f32, sodio:f32 } #[link(name = "TabelaNutricionalBiblioteca")] extern "C" { fn calcular(porcao:f32) -> TabelaNutricional; } fn main() { unsafe { calcular(20); } }

Go

// CFLAGS, CPPFLAGS, CXXFLAGS, FFLAGS e LDFLAGS // podem ajustar o comportamento das bibliotecas C // #cgo CFLAGS: -DPNG_DEBUG=1 // #cgo amd64 386 CFLAGS: -DX86=1 // #cgo LDFLAGS: -lpng // ou podemos usar pkg-config // #cgo pkg-config: png cairo // #include <png.h> import "C" // When the Go tool sees that one or more Go files use the special import "C", // it will look for other non-Go files in the directory and compile them // as part of the Go package. // Any .c, .s, .S or .sx files will be compiled with the C compiler. // Any .cc, .cpp, or .cxx files will be compiled with the C++ compiler. // Any .f, .F, .for or .f90 files will be compiled with the fortran compiler. // Any .h, .hh, .hpp, or .hxx files will not be compiled separately, // but, if these header files are changed, the package (including its non-Go // source files) will be recompiled. // mais detalhes na documentação oficial

C++

// usar LoadLibrary/GetProcAddress/FreeLibrary no Windows // ou dlopen/dlsym/dlclose no Mac e Linux // ou linkar as bibliotecas em tempo de compilação // ou adicionar as referências nas IDEs respectivas

Objective-C

// Objective-C é um superset de C // portanto pode incluir cabeçalhos // chamar funções e usar structs C // normalmente

Swift

// XCode cria um bridging header // quando inserimos arquivos C

Kotlin

// Somente Kotlin native? // import kotlinx.cinterop.*

Java - TabelaNutricional.java

package marcoLuglio.ffiExample; public final class TabelaNutricional { public float valorEnergetico; public float carboidratos; public float proteinas; public float gordurasTotais; public float gordurasSaturadas; public float gordurasTrans; public float fibraAlimentar; public float sodio; }

Java - TabelaNutricionalBibliotecaNative.java

package marcoLuglio.ffiExample; public final class TabelaNutricionalBibliotecaNative { static {System.loadLibrary("TabelaNutricionalBiblioteca");} private native TabelaNutricional calcular(float porcao); } // Also JNI // And look a new API proposal https://openjdk.java.net/jeps/412

C# - TabelaNutricionalBibliotecaNative.cs

// Adicionar a referência ao arquivo na IDE e: using System.Runtime.InteropServices; namespace MarcoLuglio.FFIExample { [StructLayout(LayoutKind.Sequential)] public struct TabelaNutricional { public float valorEnergetico; public float carboidratos; public float proteinas; public float gordurasTotais; public float gordurasSaturadas; public float gordurasTrans; public float fibraAlimentar; public float sodio; }; public static class SalarioBibliotecaNative { [DllImport( "TabelaNutricionalBiblioteca.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = @"calcular" )] public static extern TabelaNutricional calcular(float porcao); } }

Dart

import 'dart:ffi' show DynamicLibrary, NativeFunction, Int32; main() { final lib = DynamicLibrary.open('TabelaNutricionalBiblioteca.dylib'); final TabelaNutricional Function(double porcao) calcular = lib .lookup<NativeFunction<Int32 Function(Int32, Int32)>>('calcular') .asFunction(); // calcular(1); }

TypeScript

JavaScript

// No navegador não existe, mas veja // Web Assembly // Já usando node.js veja o plug-in FFI

ActionScript

// calls a host function flash.external.ExternalInterface.call('calcular', 1); // then the host needs to interface with c

Python

import ctypes TabelaNutricionalBiblioteca_dll = ctypes.cdll.LoadLibrary('TabelaNutricionalBiblioteca.dll') TabelaNutricionalBiblioteca_dll.calcular(1)

PHP

$ffi = FFI::load(__DIR__ . '/TabelaNutricionalBiblioteca.h'); // or $ffi = FFI::cdef( 'struct TabelaNutricional { float valorEnergetico; float carboidratos; float proteinas; float gordurasTotais; float gordurasSaturadas; float gordurasTrans; float fibraAlimentar; float sodio; }; TabelaNutricional calcular(float porcao);', 'TabelaNutricionalBiblioteca.so' // or 'libc.so.6'?? ); $ffi->calcular(1);

VBA / VB6

Declare Function calcular Lib "C:\pathto\TabelaNutricionalBiblioteca.dll" (ByVal porcao As Double) As TabelaNutricional

Ada

with Interfaces.C; use Interfaces.C; with Ada.Text_IO; use Ada.Text_IO; procedure Main is type TabelaNutricional is record valorEnergetico:float; carboidratos:float; proteinas:float; gordurasTotais:float; gordurasSaturadas:float; gordurasTrans:float; fibraAlimentar:float; sodio:float; end record with Convention => C; function calcular(porcao:float) return TabelaNutricional with Import => True, Convention => C; tabelaNutricional:TabelaNutricional; begin tabelaNutricional := calcular (2); end Main;

Object Pascal (Delphi)

procedure calcular; external 'TabelaNutricionalBiblioteca.dll'; // or procedure calcular; external 'TabelaNutricionalBiblioteca.dll' delayed; // or var lLibraryHandle:THandle; lCalcular:procedure; stdcall; begin lLibraryHandle := LoadLibrary('TabelaNutricionalBiblioteca.dll'); if lLibraryHandle <= 32 then begin // 32 magic constant for success lCalcular := GetProcAddress(lLibraryHandle, 'calcular'); lCalcular(); FreeLibrary(lLibraryHandle); end; end;

Ruby

require 'ffi' module LibC extend FFI::Library ffi_lib FFI::Platform::LIBC attach_function :strdup, [:string], :pointer attach_function :free, [:pointer], :void end string = "Hello, World!" duplicate = LibC.strdup(string) puts duplicate.get_string(0) LibC.free(duplicate)

Smalltalk

DLD addLibrary: 'TabelaNutricionalBiblioteca'. Object subclass: ExtLib [ ExtLib class >> openimage: aString [ (CFunctionDescriptor isFunction: 'openimage') ifTrue: [ (CFunctionDescriptor for: 'openimage' returning: #int withArgs: #(#string) ) callInto: (ValueHolder null). ] ifFalse: [ ('internal open image %1' % { aString }) displayNl ] ] ]. ExtLib calcular: 1.

Common Lisp

(cffi:load-foreign-library "TabelaNutricionalBiblioteca.so") (cffi:foreign-funcall "calcular" :string #+sbcl (sb-posix:getenv "DISPLAY") #-sbcl ":0.0" :pointer )

Haskell

  1. C++ / Rust
  2. Objective-C / C#
  3. Swift
  4. Java
  5. JavaScript

C++ e Rust são os únicos que conseguem exportar bibliotecas compatíveis com C, por se tratarem de linguagens nativas. C++ Possui grande preocupação com a compatibilidade com C, e pode misturar de maneira transparente blocos de código em C.
As bibliotecas geradas por Rust são enormes se comparados com as do C++, para comportar as regras da linguagem.
Objective-C é construído tendo C como base. Portanto, assim como C++, pode usar C de maneira transparente. Só não pode exportar para C :(
Swift?? TODO
C# possui uma sintaxe limpa para interagir com APIs em C
Java pode até ser bonitinho dentro do arquivo Java, mas o arquivo C que interage com ele é bastante complexo. Tanto que foram criadas ferramentas que geram parte deste arquivo automaticamente.
JavaScript ainda não chegou lá.

Arquitetura de plug-ins (carregamento de bibliotecas em runtime)

Rust

Go

// https://medium.com/learning-the-go-programming-language/writing-modular-go-programs-with-plugins-ec46381ee1a9

C++

Objective-C

Swift

Kotlin

Java

C#

// https://docs.microsoft.com/en-us/dotnet/core/tutorials/creating-app-with-plugin-support

Dart

// https://flutter.dev/docs/development/packages-and-plugins/developing-packages

TypeScript

JavaScript

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format - main.wasm

LLVM IR

Assembly

  1. a

A

Networking

HTTP

Rust - server.rs - actix framework

// actix uses tokio for async .await use actix_web::{web, App, HttpRequest, HttpServer, Responder}; #[get("/")] async fn index(_req:HttpRequest) -> impl Responder { "Hello from the index page!" } async fn greet(req:HttpRequest) -> impl Responder { let name = req.match_info().get("name").unwrap_or("World"); format!("Hello {}!", &name) } #[actix_web::main] async fn main() -> Result<()> { HttpServer::new(|| { App::new() .service(index) .route("/", web::get().to(greet)) .route("/{name}", web::get().to(greet)) }) .bind(("127.0.0.1", 8080))? .run() .await }

Rust - server.rs

use std::fs; use std::io::prelude::*; use std::net::TcpListener; use std::net::TcpStream; fn main() { // TODO handle SIGINT, SIGTERM, etc. println!("Starting go server on port 80"); // containers must use 0.0.0.0! localhost or 127.0.0.1 do not work! let listener = TcpListener::bind("0.0.0.0:80"); match listener { Ok(result) => { // TODO match here too listen_incoming_connections(result); }, Err(err) => println!("{}", err) } } fn listen_incoming_connections(listener:TcpListener) -> Result<(), std::io::Error> { for stream in listener.incoming() { handle_connection(stream?)?; } Ok(()) } fn handle_connection(mut stream:TcpStream) -> Result<usize, std::io::Error> { let mut buffer = [0; 1024]; let buffer_result = stream.read(&mut buffer)?; // TODO implement timeouts // formato das requisições // https://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html // methods and root uri let options = b"OPTIONS / "; let get = b"GET / "; if buffer.starts_with(options) { handle_options(buffer, stream)?; } else if buffer.starts_with(get) { handle_get(buffer, stream)?; } else { println!("TODO 404") /*( "HTTP/1.1 404 NOT FOUND", "content-type: text/html".to_string(), "404.html" )*/ }; Ok(buffer_result) } // formato das respostas // https://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html fn handle_options(buffer:[u8; 1024], mut stream:TcpStream) -> Result<(), std::io::Error> { let (status_line, headers) = ( "HTTP/1.1 200 OK", concat!( "access-control-allow-origin: *", // posso usar *, mas não se requerir autenticação com bearer: "access-control-allow-methods: options, get, post, put, delete", "access-control-allow-headers: content-type", // posso usar * ) .to_string() ); let response = format!("{}\r\n{}", status_line, headers); // TODO implement timeouts stream.write(response.as_bytes())?; stream.flush()?; Ok(()) } fn handle_get(buffer:[u8; 1024], mut stream:TcpStream) -> Result<(), std::io::Error> { let (status_line, mut headers, filename) = ( "HTTP/1.1 200 OK", "content-type: application/json".to_string(), "hello.json" ); let body = fs::read_to_string(filename)?; headers = [ headers, "\r\ncontent-length: ".to_string(), body.len().to_string() ] .concat(); let response = format!("{}\r\n{}\r\n\r\n{}", status_line, headers, body); // TODO implement timeouts stream.write(response.as_bytes())?; stream.flush()?; Ok(()) }

Rust - client.rs - ureq crate

fn main() -> Result<(), ureq::Error> { let body: String = ureq::get("http://example.com") .set("Example-Header", "header value") .call()? .into_string()?; Ok(()) }

Rust - client.rs - reqwest crate

let body = reqwest::get("https://www.rust-lang.org") .await? .text() .await?;

Go - server.go

package main import ( "fmt" "net/http" "time" ) func main() { fmt.Println("Starting go server on port 80") handler := timeoutHandler{} timeoutServer := &http.Server{ ReadHeaderTimeout: 20 * time.Second, ReadTimeout: 1 * time.Minute, WriteTimeout: 2 * time.Minute, Handler: handler, Addr: ":80", } timeoutServer.ListenAndServe() } // #region timeoutHandler struct type timeoutHandler struct{} func (handler timeoutHandler) ServeHTTP( responseWriter http.ResponseWriter, request *http.Request ) { defer request.Body.Close() switch request.RequestURI { case "/": // OK default: // TODO 404 return } /* // this is how to do a varible timeout to read the request // but it will also eat part of the write timeout timer := time.AfterFunc(5*time.Second, func() { request.Body.Close() }) // if more time is needed to write the response // reset the timer here, os in another method timer.Reset(1 * time.Second) */ var err error switch request.Method { case "OPTIONS": err = handleOptions(responseWriter, request) case "GET": err = handleGet(responseWriter, request) } if err != nil { // util.CheckError(err) // return } } // #endregion func handleOptions( responseWriter http.ResponseWriter, request *http.Request ) (err error) { // posso usar *, mas não se requerir autenticação com bearer: responseWriter.Header().Set( "access-control-allow-origin", "*" ) responseWriter.Header().Set( "access-control-allow-methods", "options, get, post, put, delete" ) // posso usar * responseWriter.Header().Set( "access-control-allow-headers", "content-type" ) return } func handleGet( responseWriter http.ResponseWriter, request *http.Request ) (err error) { responseWriter.Header().Set( "content-type", "application/json" ) responseWriter.WriteHeader(200) responseWriter.Write([]byte(`{"hello":"world"}`)) return }

Go - client.go

package main import ( "fmt" "net/http" "time" ) func main() { resp, err := http.Get("http://example.com/") resp, err := http.Post( "http://example.com/upload", "image/jpeg", &buf ) resp, err := http.PostForm( "http://example.com/form", url.Values{"key": {"Value"}, "id": {"123"}} ) if err != nil { // handle error } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) }

C++

Objective-C

Swift - client.swift

let url = URL(string: "http://www.stackoverflow.com")! let task = URLSession.shared.dataTask(with: url) {(data, response, error) in guard let data = data else { return } print(String(data: data, encoding: .utf8)!) } task.resume()

Kotlin

// Spring Boot

Java

C# - server

// Use the Asp.Net templates

C# - client.cs

var httpClient = new HttpClient(); httpClient.BaseAddress = new Uri("http://example.com"); // httpClient.DefaultRequestHeaders.Add("Accept", "application/json"); var response = await httpClient.GetAsync("/someResource"); // TODO maybe there's a faster way to check for success // without throwing exceptions? // response.EnsureSuccessStatusCode(); using var responseStream = await response.Content.ReadAsStreamAsync(); string responseString = String.Empty; using (var reader = new System.IO.StreamReader(responseStream, Encoding.UTF8)) { responseString = await reader.ReadToEndAsync(); }

Dart

// https://dart.dev/server // https://github.com/subfuzion/dart-flutter-fullstack-demo/blob/main/backend/bin/server.dart

TypeScript

JavaScript - server.mjs - nodejs

import http from 'http'; //create a server object: http.createServer(function (req, res) { res.write('Hello World!'); res.end(); }).listen(8080); // or with express https://expressjs.com/en/starter/hello-world.html // https://expressjs.com/en/advanced/best-practice-performance.html

JavaScript - client.js

fetch('http://example.com/movies.json') .then(response => response.json()) .then(data => console.log(data));

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

LLVM IR

Assembly

  1. a

A

gRPC

Protocol Buffer definition

service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) {} } message HelloRequest { string name = 1; } message HelloReply { string message = 1; } // then run protoc for the given language

Rust

// no official one yet

Go - server.go

package main import ( "context" "log" "net" "google.golang.org/grpc" pb "google.golang.org/grpc/examples/helloworld/helloworld" ) // SayHello implements helloworld.GreeterServer func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { log.Printf("Received: %v", in.GetName()) return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil } func main() { lis, err := net.Listen("tcp", port) if err != nil { log.Fatalf("failed to listen: %v", err) } s := grpc.NewServer() pb.RegisterGreeterServer(s, &server{}) if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) } }

Go - client.go

package main import ( "context" "log" "os" "time" "google.golang.org/grpc" pb "google.golang.org/grpc/examples/helloworld/helloworld" ) func main() { // Set up a connection to the server. conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock()) if err != nil { log.Fatalf("did not connect: %v", err) } defer conn.Close() c := pb.NewGreeterClient(conn) // Contact the server and print out its response. name := defaultName if len(os.Args) > 1 { name = os.Args[1] } ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name}) if err != nil { log.Fatalf("could not greet: %v", err) } log.Printf("Greeting: %s", r.GetMessage()) }

C++

Objective-C

Swift

// check apple documentation

Kotlin

Java

C# - server

public sealed class GreeterImpl : Greeter.GreeterBase { // Server side handler of the SayHello RPC public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context) { return Task.FromResult(new HelloReply { Message = "Hello " + request.Name }); } // Server side handler for the SayHelloAgain RPC public override Task<HelloReply> SayHelloAgain(HelloRequest request, ServerCallContext context) { return Task.FromResult(new HelloReply { Message = "Hello again " + request.Name }); } }

C# - client

Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure); var client = new Greeter.GreeterClient(channel); String user = "you"; var reply = client.SayHello(new HelloRequest { Name = user }); Console.WriteLine("Greeting: " + reply.Message); var secondReply = client.SayHelloAgain(new HelloRequest { Name = user }); Console.WriteLine("Greeting: " + secondReply.Message); channel.ShutdownAsync().Wait();

Dart

TypeScript

JavaScript

ActionScript

-

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

  1. a

A

GraphQL

Rust

Go

package main import ( "encoding/json" "fmt" "log" "github.com/graphql-go/graphql" ) func main() { // Schema fields := graphql.Fields { // resolver for hello "hello": &graphql.Field { Type: graphql.String, Resolve: func(p graphql.ResolveParams) (interface{}, error) { return "world", nil }, }, } rootQuery := graphql.ObjectConfig{Name: "RootQuery", Fields: fields} schemaConfig := graphql.SchemaConfig{ Query: graphql.NewObject(rootQuery) } schema, err := graphql.NewSchema(schemaConfig) if err != nil { log.Fatalf("failed to create new schema, error: %v", err) } // Query query := ` { hello } ` params := graphql.Params{Schema: schema, RequestString: query} r := graphql.Do(params) if len(r.Errors) > 0 { log.Fatalf("failed to execute graphql operation, errors: %+v", r.Errors) } rJSON, _ := json.Marshal(r) fmt.Printf("%s \n", rJSON) // {"data":{"hello":"world"}} }

C++

Objective-C

Swift

Kotlin

Java

C#

Dart

TypeScript

JavaScript

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

  1. a

A

Web sockets

Rust - Cargo.toml

tokio-tungstenite = "0.12.0"

Rust - server.rs

use std::net::TcpListener; //use tungstenite::server::accept; use tokio_tungstenite::accept_async; #[tokio::main] async fn main() { let server = TcpListener::bind("127.0.0.1:9001").unwrap(); // let size = 5; // let mut workers = Vec::with_capacity(size); for stream in server.incoming() { let worker = tokio::spawn(async move { let mut websocket = accept_async(stream.unwrap()) .await .unwrap(); loop { let msg = match websocket.read_message().await { // socket closed Ok(msg) if msg == 0 => return, // We do not want to send back ping/pong messages Ok(msg) if msg.is_binary() || msg.is_text() => msg, // websocket.write_message(msg).unwrap(); //Ok(msg) => msg, Err(e) => { eprintln!("failed to read from socket; err = {:?}", e); return; } }; } }); // workers.push(worker); } /* // close all sockets for _ in &workers { let _ = sender.send(Message::Terminate); } // wait for the close message to be acknoledged for worker in workers { let _ = worker.await; } */ }

Go - gorilla library

// great article comparing alternatives package main import ( "fmt" "net/http" "github.com/gorilla/websocket" ) var upgrader = websocket.Upgrader { ReadBufferSize: 1024, WriteBufferSize: 1024, } func main() { http.HandleFunc("/echo", func(w http.ResponseWriter, r *http.Request) { conn, _ := upgrader.Upgrade(w, r, nil) // error ignored for sake of simplicity for { // Read message from browser msgType, msg, err := conn.ReadMessage() if err != nil { return } // Print the message to the console fmt.Printf("%s sent: %s\n", conn.RemoteAddr(), string(msg)) // Write message back to browser if err = conn.WriteMessage(msgType, msg); err != nil { return } } }) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "websockets.html") }) http.ListenAndServe(":8080", nil) }

C++

Objective-C

Kotlin

// use java libraries import org.java_websocket.client.WebSocketClient import org.java_websocket.handshake.ServerHandshake import org.json.JSONException import org.json.JSONObject import java.lang.Exception import java.net.URI import javax.net.ssl.SSLSocketFactory private lateinit var webSocketClient:WebSocketClient override fun onCreate(savedInstanceState:Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } override fun onResume() { super.onResume() initWebSocket() } override fun onPause() { super.onPause() webSocketClient.close() } private fun initWebSocket() { val coinbaseUri:URI? = URI("wss://ab.com") createWebSocketClient(coinbaseUri) } private fun createWebSocketClient(coinbaseUri:URI?) { webSocketClient = object : WebSocketClient(coinbaseUri) { override fun onOpen(handshakedata:ServerHandshake?) { subscribe() } override fun onMessage(message: tring?) { setUpBtcPriceText(message) } override fun onClose(code:Int, reason:String?, remote:Boolean) { unsubscribe() } override fun onError(ex:Exception?) { // ex?.message } } } private fun subscribe() { webSocketClient.send( // json string here ) } // use https://square.github.io/okhttp/ // use https://ktor.io/docs/creating-web-socket-chat.html

Java

C#

// https://marcoluglio.github.io/br/tutorialwebsockets/ // https://docs.microsoft.com/en-us/aspnet/core/fundamentals/websockets?view=aspnetcore-5.0

Dart

// https://api.dart.dev/stable/2.13.1/dart-io/WebSocket-class.html final channel = WebSocketChannel.connect( Uri.parse('wss://echo.websocket.org'), ); StreamBuilder( stream: channel.stream, builder: (context, snapshot) { return Text(snapshot.hasData ? '${snapshot.data}' : ''); }, ) channel.sink.add('Hello!'); channel.sink.close();

TypeScript

JavaScript

const socket = new WebSocket('ws://localhost:8080'); socket.addEventListener('open', function (event) { socket.send('Hello Server!'); }); socket.addEventListener('message', function (event) { console.log('Message from server ', event.data); });

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

  1. a

A

Sockets

Rust - server.rs

Rust - client.rs

Go - server.go

package main import ( "log" "net" ) func echoServer(c net.Conn) { for { buf := make([]byte, 512) nr, err := c.Read(buf) if err != nil { return } data := buf[0:nr] println("Server got:", string(data)) _, err = c.Write(data) if err != nil { log.Fatal("Write: ", err) } } } func main() { l, err := net.Listen("unix", "/tmp/echo.sock") if err != nil { log.Fatal("listen error:", err) } for { fd, err := l.Accept() if err != nil { log.Fatal("accept error:", err) } go echoServer(fd) } }

Go - client.go

package main import ( "io" "log" "net" "time" ) func reader(r io.Reader) { buf := make([]byte, 1024) for { n, err := r.Read(buf[:]) if err != nil { return } println("Client got:", string(buf[0:n])) } } func main() { c, err := net.Dial("unix", "/tmp/echo.sock") if err != nil { panic(err) } defer c.Close() go reader(c) for { _, err := c.Write([]byte("hi")) if err != nil { log.Fatal("write error:", err) break } time.Sleep(1e9) } }

C++

Objective-C

Swift

Kotlin

Java

C#

Dart

// https://api.dart.dev/stable/2.13.1/dart-io/Socket-class.html

TypeScript

JavaScript

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

LLVM IR

Assembly

  1. a

A

JSON

Rust

use serde::{Serialize, Deserialize}; #[derive(Serialize, Deserialize, Debug)] struct Point { x: i32, y: i32, } fn main() { let point = Point { x: 1, y: 2 }; // Convert the Point to a JSON string. let serialized = serde_json::to_string(&point).unwrap(); // Prints serialized = {"x":1,"y":2} println!("serialized = {}", serialized); // Convert the JSON string back to a Point. let deserialized: Point = serde_json::from_str(&serialized).unwrap(); // Prints deserialized = Point { x: 1, y: 2 } println!("deserialized = {:?}", deserialized); }

Go

package main import ( "encoding/json" "fmt" "os" ) type response1 struct { Page int Fruits []string } type response2 struct { Page int `json:"page"` Fruits []string `json:"fruits"` } func main() { mapD := map[string]int { "apple": 5, "lettuce": 7 } mapB, _ := json.Marshal(mapD) fmt.Println(string(mapB)) res1D := &response1 { Page: 1, Fruits: []string { "apple", "peach", "pear" } } res1B, _ := json.Marshal(res1D) fmt.Println(string(res1B)) byt := []byte(`{ "num":6.13,"strs":["a","b"] }`) var dat map[string]interface{} if err := json.Unmarshal(byt, &dat); err != nil { panic(err) } fmt.Println(dat) num := dat["num"].(float64) fmt.Println(num) strs := dat["strs"].([]interface{}) str1 := strs[0].(string) fmt.Println(str1) str := `{ "page": 1, "fruits": ["apple", "peach"] }` res := response2 {} json.Unmarshal([]byte(str), &res) fmt.Println(res) fmt.Println(res.Fruits[0]) enc := json.NewEncoder(os.Stdout) d := map[string]int { "apple": 5, "lettuce": 7 } enc.Encode(d) }

C++

// use an external library

Objective-C

Swift

import Foundation let str = "{\"names\": [\"Bob\", \"Tim\", \"Tina\"]}" let data = Data(str.utf8) let json = try? JSONSerialization.jsonObject(with: data, options: []) if let dictionary = jsonWithObjectRoot as? [String: Any] { if let number = dictionary["someKey"] as? Double { // access individual value in dictionary } for (key, value) in dictionary { // access all key / value pairs in dictionary } if let nestedDictionary = dictionary["anotherKey"] as? [String: Any] { // access nested dictionary values by key } } if let array = jsonWithArrayRoot as? [Any] { if let firstObject = array.first { // access individual object in array } for object in array { // access all objects in array } for case let string as String in array { // access only string values in array } } // we need to manually map the dictionary to a struct struct Restaurant { enum Meal: String { case breakfast, lunch, dinner } let name: String let location: (latitude: Double, longitude: Double) let meals: Set<Meal> } extension Restaurant { init(json: [String: Any]) throws { // Extract name guard let name = json["name"] as? String else { throw SerializationError.missing("name") } // Extract and validate coordinates guard let coordinatesJSON = json["coordinates"] as? [String: Double], let latitude = coordinatesJSON["lat"], let longitude = coordinatesJSON["lng"] else { throw SerializationError.missing("coordinates") } let coordinates = (latitude, longitude) guard case (-90...90, -180...180) = coordinates else { throw SerializationError.invalid("coordinates", coordinates) } // Extract and validate meals guard let mealsJSON = json["meals"] as? [String] else { throw SerializationError.missing("meals") } var meals: Set<Meal> = [] for string in mealsJSON { guard let meal = Meal(rawValue: string) else { throw SerializationError.invalid("meals", string) } meals.insert(meal) } // Initialize properties self.name = name self.coordinates = coordinates self.meals = meals } }

Kotlin

import kotlinx.serialization.json //... @Serializable data class User(val name:String, val yearOfBirth:Int) val data = User("Louis", 1901) val string = Json.encodeToString(data) println(string) // {"name":"Louis","yearOfBirth":1901} val obj = Json.decodeFromString(string) // val obj = Json.parse(User.serializer(), string) println(obj) // User(name=Louis, yearOfBirth=1901)

Java

C#

using System.Text.Json; public sealed class CsEntity { public string Id { get; set; } = String.Empty; public IEnumerable<OtherCsEntity>? OtherProp { get; set; } } var jsonSerializerOptions = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, IncludeFields = true }; var fromJson = await JsonSerializer .DeserializeAsync<CsEntity>( responseString, jsonSerializerOptions ); var fromJsonList = JsonSerializer .Deserialize<IEnumerable<CsEntity>>( responseString, jsonSerializerOptions );

Dart

// https://dart.dev/guides/json // using json_serializable package import 'package:json_annotation/json_annotation.dart'; part 'user.g.dart'; @JsonSerializable() class User { User(this.name, this.email); String name; String email; factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json); Map<String, dynamic> toJson() => _$UserToJson(this); } Map<String, dynamic> userMap = jsonDecode(jsonString); var user = User.fromJson(userMap); // using import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; import 'package:built_collection/built_collection.dart'; part 'person.g.dart'; abstract class Person implements Built<Person, PersonBuilder> { static Serializer<Person> get serializer => _$personSerializer; // Can never be null. int get id; @nullable int get age; @nullable @BuiltValueField(wireName: 'first_name') String get firstName; @nullable BuiltList<String> get hobbies; Person._(); factory Person([void Function(PersonBuilder) updates]) = _$Person; } // TODO

TypeScript

const fromJson:SomeType = JSON.parse('{ "a": "b" }');

JavaScript

const fromJson = JSON.parse('{ "a": "b" }');

ActionScript

Python

import json toJson = { "a": "b" } jsonString = json.dumps(x) # no native direct mapping... parsedTuples = json.loads(jsonString)

PHP

$json = '{"foo-bar": 12345}'; $obj = json_decode($json); print $obj->{'foo-bar'};

VBA / VB6

# use external library

Ada

with Ada.Text_IO; with GNATCOLL.JSON; procedure JSON_Test is use Ada.Text_IO; use GNATCOLL.JSON; JSON_String:constant String := "{""name"":""Pingu"",""born"":1986}"; Penguin:JSON_Value := Create_Object; Parents:JSON_Array; begin Penguin.Set_Field( Field_Name => "name", Field => "Linux" ); Penguin.Set_Field( Field_Name => "born", Field => 1992 ); Append(Parents, Create("Linus Torvalds")); Append(Parents, Create("Alan Cox")); Append(Parents, Create("Greg Kroah-Hartman")); Penguin.Set_Field( Field_Name => "parents", Field => Parents ); Put_Line(Penguin.Write); Penguin := Read(JSON_String, "json.errors"); Penguin.Set_Field( Field_Name => "born", Field => 1986 ); Parents := Empty_Array; Append(Parents, Create("Otmar Gutmann")); Append(Parents, Create("Silvio Mazzola")); Penguin.Set_Field( Field_Name => "parents", Field => Parents ); Put_Line (Penguin.Write); end JSON_Test;

Object Pascal (Delphi)

uses System.JSON; procedure ParseJSonValue; var JSonValue:TJSonValue; st:String; Branch:String; begin st := '{"data":{"results":[{"Branch":"ACCT590003"}]}}'; JsonValue := TJSonObject.ParseJSONValue(st); Branch := JsonValue.GetValue('data.results[0].Branch'); JsonValue.Free; end; // embarcadero has 2 more libraries to work with // http://docwiki.embarcadero.com/RADStudio/Sydney/en/JSON

Ruby

require 'json' source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}' ruby = JSON.parse(source, {object_class: OpenStruct}) json = '["foo", 1, 1.0, 2.0e2, true, false, null]' ruby = JSON.parse(json) json = '{"a": "foo", "b": 1, "c": 1.0, "d": 2.0e2, "e": true, "f": false, "g": null}' ruby = JSON.parse(json)

Smalltalk

Common Lisp

Haskell

  1. a

A

Web Assembly

Rust

Go

C++

Objective-C

Swift

Kotlin

Java

C#

Dart

TypeScript

JavaScript

ActionScript

Python

PHP

VBA / VB6

Ada

Object Pascal (Delphi)

Ruby

Smalltalk

Common Lisp

Haskell

Web Assembly text format

LLVM IR

Assembly

  1. a

A