¿Qué extraño de Python?

llorando.jpg

por Juanjo Conti

jjconti@gmail.com - @jjconti

PyDay Litoral 2015

.

¿Qué extrañé (y qué no) de Python en los últimos cuatro lenguajes con los que trabajé?

llorando.jpg

por Juanjo Conti

jjconti@gmail.com - @jjconti

PyDay Litoral 2015

Primera novia

Balada de la primera novia, Alejandro Dolina

(El libro del fantasma)

El poeta Jorge Allen tuvo su primera novia a la edad de doce años. Guarden las personas mayores sus sonrisas condescendientes. Porque en la vida de un hombre hay pocas cosas más serias que su amor inaugural.

Después de una triste fiestita de fin de curso, ya no volvió a verla ni a tener noticias de ella. Sin embargo siguió queriéndola a lo largo de sus años. Jorge Allen se hizo hombre y vivió formidables gestas amorosas. Pero jamas dejo de llorar por la morocha ausente.

Los lenguajes

PHP: el feo

Ruby: el gemelo malvado

Swift: el nuevo

Clojure: el raro

PHP

El feo.

feo.jpg

http://phpepl.herokuapp.com/

PHP

$a[1]()

PHP

Extraño una sintaxis simple para rebanar arrays

(y otras operaciones con arrays)

$a = array("a", "b", "c", "d", "e");

array_slice($a, 2); // "c", "d", "e"

array_slice($a, -2, 1); // "d"

array_slice($a, 0, 3); // "a", "b", "c"

PHP

En Python:

a = ["a", "b", "c", "d", "e"]

a[2:] # ['c', 'd', 'e']

a[-2:-1] # ['d']

a[:3] # ['a', 'b', 'c']

a[::2] # ['a', 'c', 'e']

PHP

Algo parecido pasa con los strings

substr("abcdef", -1); // "f"

substr("abcdef", -2); // "ef"

substr("abcdef", -3, 1); // "d"

PHP

En Python:

"abcdef"[-1:] # 'f'

"abcdef"[-2:] # 'ef'

"abcdef"[-3:-2] # 'd'

"abcdef"[::-2] # 'fdb'

PHP

Listas por comprensión

[x*x for x in range(10)]
array_map(function($x) {
    return $x*$x;
}, range(0, 9))

PHP

Listas por comprensión

[x*x for x in range(10) if x > 4]
array_filter(
    array_map(...)
)

PHP (NO)

Python puede hacerte un mejor programador porque el lenguaje es consistente, toma buenas ideas de la programación funcional, es limpio, fácil de leer y tiene un montón de constructores útiles como decoradores, iteradores, y listas por comprensión.

Ruby

gemelo.png

.

Diferencias

  • Todo tiene valor de verdad true excepto false y nil

  • Los strings son mutables

  • Arrays, Hashes

  • Símbolos

  • Bloques

  • Cuestiones sintácticas

Valores de verdad

Todo tiene valor de verdad true excepto false y nil

def que_es obj
  obj
  ? "#{obj} es true"
  : "#{obj} es false"
end
que_es [] # "[] es true"

que_es 1 # "1 es true"

que_es false # "false es false"

Strings mutables

s = "Cactus"
s[0] = 'KKKK'
"KKKKactus"

Arrays

  • Arrays y sus índices

a = []
a[2] = 1
[nil, nil, 1]
a[10] # nil

Array * string

array = [1, 2, 3, 4, 100]
array * 2

[1, 2, 3, 4, 100, 1, 2, 3, 4, 100]
array * '|'

"1|2|3|4|100"
[1, [2,3], 4, [[[5]]]] * ','

"1,2,3,4,5"

Hashes

Recuerdan el orden de inserción.

h = {}
h[1] = "a"
h[2] = "b"
h[3] = "c"
h.delete(1)
h[1] = "A"
h.keys
[2, 3, 1]

Hashes

Se pueden usar objetos mutables como claves

a = []; h = {a => 2}
h.default = 'defecto'
a << 1

{[1]=>2}
h[a] # "defecto"
h.rehash; h[a]

2

Símbolos

:simbolo
:"Con espacios"

"hola".object_id # 70262217568780
"hola".object_id # 70262213790460

:hola.object_id # 1171208
:hola.object_id # 1171208

Sintaxis

<expresion> if <condición>

a = 1 if true
api_key = "zzzzzzz" if env.production?
if true
  puts "no no no no"
end if false

Sintaxis

El parser ve aunque no ejecute.

q.nil? # NameError

q = 1 if q.nil? # 1
if false
  f = 1
end
f.inspect # nil

Sintaxis

Parámetros con valores por defecto referenciando parámetros previos.

def parametros a, b=a*2
  [a, b]
end

parametros 10
[10, 20]

Sintaxis

Captura genérica de parámetros no necesariamente al final.

def ejemplo(a, *b, c)
    puts [a, b, c]
end

ejemplo 1, 2, 3, 4, 5
[1, [2, 3, 4], 5]

Swift

Es un lenguaje compilado y de tipado estático, pero tiene inferencia de tipos.

mapple.jpg

.

Screensaver Ninja

screensaverninja.png

http://www.screensaver.ninja

Swift

var s = "Hola"

var s : String = "Hola"
  • Permite definir constantes: let

  • Los enteros tienen límite (en Python no)

  • Nombres de métodos más largos/dificiles de recordar

    • upper / uppercaseString

    • startswith / hasPrefix

  • Usar listas o diccionarios con distintos tipos de datos puede llevar a complicaciones

  • Swift tiene bloques como Ruby

Seguridad

  • Intenta ser un lenguaje seguro, evitando excepciones de punteros nulos

var str = "Hola, PyDay"
str = nil

// Cannot assign a value of type 'nil'
// to a value of type 'String'

Opcionales

var str : String? = "Hola, PyDay"
  • Referencias a nil?

  • El signo de pregunta luego del tipo indica que la variable str es un opcional

    • Su valor puede o no existir

Opcionales

  • Uso

    • en un contexto que espere un opcional

    • explícitamente "unwrapped"

print(str) // Optional("Hola, PyDay")
print(str!) // "Hola, PyDay"

str + ", Bienvenido"
// Value of optional type 'String?'
// not unwrapped

Opcionales

str! + ", Bienvenido"

str = nil

str! + ", Bienvenido"
// Error en tiempo de ejecución

if str {
    str! + ", Bienvenido"
}

Copia no opcional

  • Copiar como no opcional en un scope

if let str = str {
    str + ", Bienvenido"
}

if let nombre = persona.nombre_completo {
    nombre + ", Bienvenido"
}

Copia no opcional mutable

  • Se puede usar var en lugar de let para hacer una copia mutable

if var producto = producto_sel {
    producto.baja()
    print(producto.stock())
}

Asignaciones

  • Una variable declarada como opcional, no se puede asignar a una no declarada como opcional

var n: String = str
// produce un error en tiempo
// de compilación
  • Al igual que si se trata de asignar nil a una variable no declarada como opcional

Optional chaining

if object.other?.more?.property {
    // existe la propiedad
} else {
    // NO existe la propiedad
}
  • Más información sobre opcionales en el capítulo Optionals de Swift pocket reference

Clojure

raro.jpg

Funcional.

Todos los valores son inmutables.

.

Ejemplo

(+ 1 1)

(conj '(1 2 3) (+ 2 2))
2

'(1 2 3 4)

Macros

(defmacro postfix-notation
  "I'm too indie for prefix notation"
  [expression]
  (conj (butlast expression)
        (last expression)))

(postfix-notation (1 1 +))
; 2
(macroexpand '(postfix-notation (1 1 +)))
; (+ 1 1)

Ej en Ruby

assert_difference("User.count()", 1) do
  add_user_to_database()
end

assert_difference("User.count()", 0) do
  modify_user_on_the_database()
end

assert_difference("User.count()", -1) do
  remove_user_from_the_database()
end

Ej en Clojure

(assert-difference (users-count) 1
                   (add-user 'ramon2))

(assert-difference (users-count) 0
                   (update-user 'ramon))

(assert-difference (users-count) -1
                   (remove-user 'ramon))

Solución

(defmacro
    assert-difference
    [form delta & body]
    `(let [count# ~form]
        ~@body
         (is (=
             (+ count# ~delta)
             ~form))))

¡Muchas gracias!

¿Preguntas?

pensando.png

Notas

Más información

La presentación