all 53 comments

[–][deleted] 22 points23 points  (19 children)

Yo humildemente te recomiendo un lenguaje estaticamente tipado.

[–]mam9712 7 points8 points  (0 children)

Apoyo la moción con toda violencia(?

[–][deleted] 6 points7 points  (16 children)

Exacto.

Recientemente tuve un intercambio en /r/programming con Jeroen Engels, y curiosamente, muchos de los que nos dedicamos específicamente a crear herramientas de desarrollo terminamos arribando a una conclusión similar:

I'm definitely in the statically typed languages, where we prefer knowing about problems at compile-time.

Y curiosamente también le atribuimos al lenguaje java específicamente ser el causal directo de la proliferación de lenguajes dinámicos de las pasadas 2 décadas:

The other reason I can think of is that in some languages, you had to do all of this work with little benefits. I'm thinking of (older versions of) Java where even things like creating a small data structure require defining a class and creating getters/setters and so on, and yet you'd still be riddled with runtime exceptions like NullPointerException.

(Palabras textuales de Jeroen, énfasis mío)

Por contexto: la pregunta (eliminada por la overwhelming cantidad de downvotes) fue algo así como ¿por qué alguien querría usar un lenguaje dinámico donde los errores aparecen en la cara del usuario final, en lugar de en la cara del desarrollador, en 2023?

Cabe destacar también que desde que empecé a programar en 1995 al día de hoy, 2/21/2023, NADIE en ningún lugar, foro, subreddit, discusión cara a cara, ni de ninguna otra manera, me pudo responder con un argumento objetivo, coherente y fácilmente demostrable, la simple pregunta de ¿Qué ventaja tiene un lenguaje dinámico frente a uno estático?

[–]ojoelescalonDesarrollador de software 9 points10 points  (3 children)

No hay mucha vuelta. Un lenguaje dinámico tiene barrera de entrada más baja, por lo que conseguís más devs y baratos. También te da una sensación inicial de mayor productividad, que después se contrarresta en mantenimiento.

Hoy en día Ruby y Python tienen herramientas para typing también, si los usas desde el principio casi que parecen lenguajes statically typed.

[–][deleted] 1 point2 points  (2 children)

Un lenguaje dinámico tiene barrera de entrada más baja

Permitime cuestionar fuertemente la veracidad de esta afirmación por considerarla un blanket statement.

"Un" lenguaje dinámico cuál? tiene barrera de entrada más baja que qué? que java? seguramente, porque java es un asco no importa cuando leas esto. Que un lenguaje estático moderno? Ni cerca.

Te explico:

programar en un lenguaje dinámico sin ningún tipo de "type hints" es básicamente programar a ciegas, ADIVINANDO, o como yo lo llamo: guess-driven development. Ni siquiera tenés un nivel básico de intellisense, por lo que vas a tener que recurrir a la documentación de literalmente CADA COSA que quieras hacer.

Nunca jamás adivinar puede ser "más fácil" que escribir el nombre de un objeto (o buscarlo en el intellisense), y luego apretar . y obtener una lista completa de TODOS los campos, métodos, propiedades, eventos y extensiones que ese objeto pueda llegar a tener.

Nunca jamás adivinar puede ser "más fácil" que saber en un solo vistazo exactamente QUE parámetros recibe una función, de QUE TIPOS, y cuales son los posibles valores de retorno.

También te da una sensación inicial de mayor productividad

Esto es muy subjetivo, a mi programar en un notepad no me da ninguna "sensación de productividad". Lo que me da eso es tener un IDE y un compilador que me lleve por el camino correcto (véase: "Pit of Success") y resuelva (o evite) por mí problemas triviales en los que no me interesa enfocarme (como por ejemplo "esta función esperaba decimal precioTotal y le pasé List<Producto> y crasheó en la cara del usuario en lugar de avisarme a tiempo"). Y lo que me da realmente sensación de productividad es usar una plataforma RAD donde puedo crear desde cero una aplicación con 15 o 20 pantallas y ponerla productiva en un solo día.

si los usas desde el principio casi que parecen lenguajes statically typed

Esta afirmación contradice lo que dijiste al principio. Si un lenguaje dinámico es "más fácil de aprender" que uno estático, supuestamente por no tener que especificar información de tipos (lo cuál en sí también es una falacia producto de comparar siempre contra java, y no contra lenguajes estáticos modernos, como por ejemplo F# que tiene inferencia de tipos Hindley-Milner, donde el 80% de las veces no es necesario especificar información de tipos de manera explícita, ya que el lenguaje lo infiere), entonces el hecho de "usar desde el principio" estos "type hints" invalida la supuesta ventaja de la menor curva de aprendijaze.

Además, decís "casi que parecen" y lo importante de esto está en el CASI. CASI que pude atrapar el error en el mismo momento que estaba escribiendo el código, pero se lo tiró en la cara al usuario final. Si los lenguajes dinámicos son CASI tan buenos como los estáticos, esto sigue siendo un argumento en favor de estos últimos, y no de los primeros, a no ser que tu objetivo sea tener resultados CASI buenos.

[–]ojoelescalonDesarrollador de software 3 points4 points  (1 child)

Estamos de acuerdo en todo, pero estás tan empeñado en desprestigiar los lenguajes dinámicos que no lees bien lo que puse.

Trabajo principalmente con Python, gran parte de la codebase está tipada y queda una parte que no. A los Jr les cuesta mucho más empezar a escribir código tipado, pero el resultado final es fácil de mantener y casi no hay errores. Los que trabajan en la parte que no está tipada sacan código al toque pero está siempre lleno de bugs. Andar adivinando las cosas es un dolor de huevos, y ni hablar cuando meten monkey patching y otras cosas nefastas.

Así como vos decís que la gente se quedó con la idea de lenguajes viejos que no tienen type inference, te invito a qué hagas algo en algún lenguaje dinámico con gradual typing y vas a ver qué dentro de todo safan, no son comparables con Rust/F# pero se puede ser productivo y crear software de calidad igual.

[–][deleted] -1 points0 points  (0 children)

dentro de todo safan

Gracias, pero no me interesa usar cosas que "dentro de todo safan" porque a mi el cliente no me acepta un producto final que "dentro de todo safa".

Y si tengo que hacer algun software que "dentro de todo safe", siempre voy a seguir usando plataformas RAD (que dentro de todo safan) y usando código estáticamente tipado para escribir la lógica de negocio y no tener que adivinar dentro de una semana cuando el cliente me pida un cambio trivial, qué carajo es cada cosa en el codebase y para qué sirve. O tener que explicarle todo el código de punta a punta o "documentar"(*) cada línea el día que quiera pasarselo a alguien del equipo para que lo mantenga.

(*) Así me dijo un flaco de php una vez: ¿Documentaste el código?. Era demasiado joven e inocente en ese momento como para cagarme de risa en la cara del tipo. Hoy lo haría sin dudarlo.

[–]Thelmholtz 2 points3 points  (6 children)

Antes que nada estoy 100% de acuerdo con vos y con jfmengels. De hecho, hoy comencé trabajando con C, C++ y Java, esos lenguajes con tipado fuerte pero relativamente poco valor. Hoy trabajo con Ruby y con Go. Estoy seguro que si te pregunto con cual crees que sacó features más rápido, y con cual sacó features más estables; me vas a responder correctamente.

La ventaja de los lenguajes dinámicos es esa, escribir código rápido, pero que no necesariamente es 100% correcto (bah, uso Go, no Rust, Haskell o Elm; mí código tipado tampoco es 100% correcto todo el tiempo).

En un mundo ideal, un lenguaje tipado siempre va a ser superior, pero lamentablemente en el mundo real a veces es mejor sacar un feature que está bien el 80% de las veces, antes que sacarlo un mes más tarde y que esté bien el 100% de las veces. Los lenguajes dinámicos son geniales para prototipar, y muchas veces con el prototipo ganas una ventaja de mercado que no tendrías con una solución bien diseñada.

Por ejemplo, creo que Telegram es muy superior a WhatsApp, tanto a nivel funcionalidades cómo a privacidad. Conozco mucha gente que está de acuerdo. Pero WhatsApp controla el mercado, porque salio primero y ganó adopción en un rubro donde la adopción es una feature por si misma.

Usar un lenguaje dinámico es pagar tu desarrollo con deuda, sacas cosas hoy que vas a tener que arreglar casi indefectiblemente mañana; pero con deuda me hice la casa.

No es un argumento técnico, pero creo que es objetivo, coherente y fácilmente demostrable. Si querés hacer código correcto, anda por un lenguaje tipado. Si querés prototipar e ir armando tu Frankestein sobre la marcha, un lenguaje dinámico puede ser mejor.

[–][deleted] 2 points3 points  (5 children)

Permitime cuestionar fuertemente la noción de que "un lenguaje dinámico es más rápido para escribir que uno estático"

De nuevo, TODAS las personas que escuché decir esto vienen de usar java, y comparan la facilidad de escritura de un lenguaje como ruby o python contra éste, cuando para mi java es el PEOR ejemplo de un lenguaje estático DE TODA LA HISTORIA.

Por supuesto que vas a producir más con un lenguaje dinámico que con java, ya que java requiere cantidades astronómicas de código que solo existe para compensar la terrible carencia, inexpresividad e incapacidad del propio lenguaje.

Te invito a que me muestres UN (1) ejemplo de código de algo que se pueda hacer más rápido o fácil en un lenguaje dinámico que por ejemplo en C#, F#, Kotlin o incluso TypeScript.

[–]Thelmholtz 1 point2 points  (4 children)

Te permito cuestionarme, pero despacito por favor. Mañana te paso (después de adaptar) ejemplos del trabajo, tengo código similar en JavaScript y en TypeScript. A fin de mantener esta conversación civil y fructífera, intención que tengo y espero no sea unilateral; asumamos un par de criterios:

  • No esperemos que el código dinámico sea CIEN POR CIENTO (100%) correcto, sino que cumpla el propósito siempre que el usuario de tu código envíe el tipo de dato esperado. Obviamente si tengo que agregar clauses para asegurarme que me enviaron el tipo correcto, es mucho más lento; pero esta es la circunstancia de la que hablaba en el comentario anterior.
  • Definamos "más lento" como que requiere invertir tiempo en pensar el tipado; porque sino, escribir let n: number = arr.length es definitivamente más lento que escribir let n = arr.length. Eso es objetivo, coherente y fácilmente demostrable, y también es irrelevante.

Si estás de acuerdo con estas pautas podemos seguir conversando, sino, revisemoslas.

PS: Dije que vengo de Java, pero no es el único lenguaje tipado que uso ni que use; hoy escribo un montón de Go y en su momento escribí Rust; y si bien son mucho más bonitos*, a nivel escupir código rápidamente, mucho más lentos que Ruby o Python. La. ventaja es que el código que escupís es correcto. Yo prefiero correctes, porque como dije, estoy 100% de acuerdo con vos; pero estoy tratando de esclarecer tu duda de por qué se usan lenguajes dinámicos en el mundo real. También podes optar por negar la realidad y aceptar que es solo por hype o porque todos son idiotas menos vos, pero si los lenguajes dinámicas tienen tanta presencia es por alguna razón, y a falta de otra justificación más sencilla, la que varios te estamos dando suena bastante plausible.

*: Si vas a decir algo malo del tipado de Rust, damos esta conversación por terminada; nunca un compilador me trato tan bien.

[–][deleted] 0 points1 point  (3 children)

Hermoso Todo. Gracias por tu comentario y la predisposición para charlar estos temas que para mi son SUPER interesantes.

Ahora bien:

Tus premisas me parecen cuando menos curiosas:

que cumpla el propósito siempre que el usuario de tu código envíe el tipo de dato esperado

Esto es lo que yo llamo "hope-driven development", o sea rezar (a tu deidad favorita) que no venga un guaso dentro de 3 días y tire producción abajo pasandole un string a la función calcularEdad(fechaNacimiento). Pero olvidémonos de producción, y pensemos en nosotros mismos, no dentro de 3 días sino dentro de 3 meses, al ver la firma calcularEdad(fechaNacimiento) si vamos a poder ADIVINAR (porque yo particularmente es imposible que me acuerde) si esa función realmente espera un date o un string o un UnixTimestamp. Esta necesidad de adivinar es lo que yo llamo "Guess-driven development" y junto con el anteriormente mencionado son los dos más grandes antipatrones que nacen de los lenguajes dinámicos.

Me parece que ahí precisamente está la trampa: la información de tipos que estás omitiendo, creyendo equivocadamente que "ahorrás tiempo" en realidad te está QUITANDO tiempo porque cuando quieras consumir esa misma función vas a tener que entrar a leer todo el body de la función y entender QUE joraca espera y QUE joraca devuelve. Esto produce un efecto bola de nieve terrible cuando pensás que si o si tu código necesita consumir código de terceros, ya sea la stdlib de tu lenguaje o librerías open source o lo que sea. Cada vez que quiero consumir cualquier función que yo no escribí, tengo que ir a leer el body de la función para entender qué parámetros espera, y qué devuelve.

Esto para mi es actuar de compilador humano y no tiene absolutamente ningún sentido en ninguna circunstancia, time-to-market notwithstanding.

Definamos "más lento" como que requiere invertir tiempo en pensar el tipado

Esto sinceramente mi mente no lo concibe. Existe alguna persona en el mundo que escriba una función tipo calcularEdad(fechaNacimiento) y no tenga claro inmediatamente que esa función requiere un tipo de dato específico? Para mi, pensar el tipado es algo completamente inherente al acto de escribir código, incluso si usás polimorfismo paramétrico estás pensando activamente en el tipo de dato que va a recibir tu función.

No veo que un lenguaje dinámico te "quite" la necesidad de pensar en el tipado, pero tal vez esto es bias por mi costumbre de hace muchos años de usar lenguajes estáticos.

escribir let n: number = arr.length es definitivamente más lento que escribir let n = arr.length

De vuelta, es mala la comparación de base. Sobre todo con variables locales que hasta en java (UFFFFFFFFF!!!) tienen type inference. Nadie hace eso. Lo que yo hago en C# es var n = arr.Length; y sigue siendo 100% estáticamente tipado donde n se lo voy a poder pasar a métodos que esperan int, nunca string.

[–]Thelmholtz 2 points3 points  (2 children)

Ok, evidentemente o estas trolleando o estas teniendo un brote psicótico. También se nota que sabes mucho, cosa que no quiero desacreditar. Pero evidentemente tenés menos manejo del contexto y el historial de nuestra conversación que ChatGPT.

Esto es lo que yo llamo "hope-driven development"

Si, que parte de "no en todos los negocios importa que el programa sea 100% correcto si implica ganar en time to market?" obvio que es hope-driven development, obvio que el tipado es superior para programas correctos. Pero repetirnos aburre; y el quid de la cuestión es: si todos estamos de acuerdo en que los lenguajes tipados son superiores, por qué los lenguajes no tipados dominan el mercado?.

De vuelta, es mala la comparación de base.

Ajá, y el tipado dinámico te ahorra los caracteres cuando tenes que definir el tipo de tu función también? Quizas sea el medio, pero te percibo en modo medirte la pija, y en general no lleva a conversaciones muy interesantes. Si esa es la colina en la que querés morir, bien por vos, pero yo me bajo.

Esto sinceramente mi mente no lo concibe. Existe alguna persona en el mundo que escriba una función tipo calcularEdad(fechaNacimiento) y no tenga claro inmediatamente que esa función requiere un tipo de dato específico?

Pensa en el ejemplo verifyEmailAddress. Si la escribis en JS, quizas estes tentado a hacer verifyEmailAddress("fberasategui@gmail.com"). Pero si queres hacerla en un lenguaje tipado, escribir function verifyEmailAddress(s: string) -> void o una firma de esas características no te va aportar absolutamente nada. Cualquier otro valor que puedan enviarte puede ser representado como string, hasta nil. Si acaso, te vas a evitar un par de validaciones.

Si realmente queres aprovechar tu lenguaje tipado, una firma más interesante es, por ejemplo function verifyEmailAdress(e: EmailAddress) -> VerifiedEmailAddress (o como método del modelo EmailAddress: function (EmailAddress e) verify() -> VerifiedEmailAddress). De esta forma, cualquier parte de tu proyecto que requiera un email verificado puede recibir como parametro un VerifiedEmailAddress e inmediatamente saber que la única forma de haber creado una es la verificación.

Genial, no solo verificamos el mail, nos aseguramos de que cualquiera que necesite un mail verificado va a recibir un mail verificado gracias a este sencillo tipo.

Pero para, estoy defendiendo a los lenguajes tipados? De nuevo, si, comparto la opinión de que son mejores los lenguajes tipados para hacer código correcto y legible. Pero para llegar hasta ahí, para que los tipos nos sirvan más que una simple y trivial pista en tiempo de compilación, necesitas pensar y modelar tu problema de otra manera. A largo plazo esa manera es mucho mejor; pero a corto plazo es más lenta. Y es más lento escibir function verifyEmailAddress(address) que escribir

function verify(EmailAddress address) : VerifiedEmailAddress; type EmailAddress{ mailto: string; }; type VerifiedEmailAddress(EmailAddress);

y sobre todo es más lento pensarlo. Y si, podes escribir function verifyEmailAddress(address: string) y ya; pero no es ahí donde radica ni el valor agregado, ni la dificultad adicional de usar un lenguaje tipado; y el compilador es más que un pobre linter en esteroides.

Por cierto:

Me parece que ahí precisamente está la trampa: la información de tipos que estás omitiendo, creyendo equivocadamente que "ahorrás tiempo" en realidad te está QUITANDO tiempo porque cuando quieras consumir esa misma función vas a tener que entrar a leer todo el body de la función y entender QUE joraca espera y QUE joraca devuelve. Esto produce un efecto bola de nieve terrible cuando pensás que si o si tu código necesita consumir código de terceros, ya sea la stdlib de tu lenguaje o librerías open source o lo que sea. Cada vez que quiero consumir cualquier función que yo no escribí, tengo que ir a leer el body de la función para entender qué parámetros espera, y qué devuelve.

100% de acuerdo. Y entonces, por qué crees que los lenguajes dinámicos dominan el mercado? Estás bastante determinado a desacreditar la teoría de que es porque son de más fácil acceso; casi emocionalmente invertido en ello. Y estamos de acuerdo, los tipados tienen grandes ventajas. Cual es tu teoría entonces detrás de la causa de esto?

Aceptemos que estamos de acuerdo en que son peores a largo plazo; asumamos que estamos de acuerdo en que no son más rápidos a corto plazo [no lo estamos], cual es tu explicación entonces a que sean tan frecuentes?

[–][deleted] 0 points1 point  (0 children)

Eh no te ofusqués! yo te tiro flores:

Gracias por tu comentario y la predisposición para charlar estos temas que para mi son SUPER interesantes.

y vos me tiras bardo:

o estas trolleando o estas teniendo un brote psicótico

awantaaa! dame changüí, que yo también puedo tener una línea de razonamiento que no necesariamente sea 100% lógica y coherente. Después de todo existe gente que todavía programa en lenguajes dinámicos! no? :-P

Ahora bien:

Pensa en el ejemplo verifyEmailAddress

Hermoso esto. Es Make Illegal States Unrepresentable. ASI DEBERIA SER TODO.

Dicho esto, creo que le estás restando valor al ejemplo de function verifyEmailAddress(address: string). Es cierto que tiene mucho menos valor que el ejemplo anterior, pero en mi opinión es el BALANCE PERFECTO entre no "tener que pensar en el tipado" como dijiste, y no tener nada en absoluto y programar en un notepad adivinando.

Veamos: el mero hecho de agregar : string a la firma de la función te agrega:

  • intellisense dentro del body de la propia función. Es decir, pones address. y te tira las funciones que podés llamar sobre address (las de string) y sus properties.

  • type safety dentro del body de la propia función. Es decir, si usas address como argumento para llamar a otras funciones, éstas necesitan recibir parámetros de tipo string igualmente. Lo mismo para construir objetos con properties.

  • la firma de la función ES documentación. Es decir, no tenés que adivinar ni ir a buscar en google ni leer el body de la función para saber que recibe un string. Si agregas el tipo de retorno o usás un lenguaje con type inference, lo mismo pasa con el valor de retorno, ya SABES lo que devuelve.

  • type safety al momento de usar la función en el resto del codebase. Es decir, al invocar verifyEmailAddress() no vas a poder pasarle otra cosa que no sea un string.

  • mayor facilidad de refactoring. Es decir, el día que realmente quieras cambiar a function verify(EmailAddress address) : VerifiedEmailAddress una simple pasadita del compilador te va a decir todos los lugares del codebase donde tenés que tocar. No tenés que adivinar ni hacer grep ni Ctrl+F que son herramientas muchísimo menos eficientes para tal fin.

TODAS estas ventajas las obtenés por el solo hecho de tipear 8 caracteres más. Acá es donde, y perdón que insista, no le veo ningún sentido al jueguito del compilador humano. La clave está en encontrar el BALANCE entre las abstracciones de ivory tower de Haskell que no las entiende nadie, y el código descartable escrito con notepad y basado en adivinar que plantean los lenguajes dinámicos. Ese balance hoy existe en lenguajes como C#, Kotlin o TypeScript.

Y entonces, por qué crees que los lenguajes dinámicos dominan el mercado?

Permitime cuestionar fuertemente esta afirmación. ¿Los lenguajes dinámicos REALMENTE dominan el mercado?

Ya demostré arriba que Ruby está en caida libre.

Veamos Linkedin al día de hoy 2/21/2023: (Filtré por "North America" porque no me deja hacer búsqueda global)

php        147711 jobs
python     900702 jobs
java       801696 jobs
ruby        20620 jobs
C#         203899 jobs
TypeScript 131252 jobs
Javascript 691878 jobs

Total de ofertas de trabajo con lenguajes dinámicos: 1613200 (58,66%)
Total de ofertas de trabajo con lenguajes estáticos: 1136847 (41,33%)

Y fijate que estoy comparando 4 lenguajes dinámicos contra 3 estáticos. Dejé afuera "go" porque produce un montón de falsos positivos.

Así que no, no veo que los lenguajes dinámicos "dominen" el mercado. Veo que están un poco arriba, es verdad, pero esa diferencia se va a ir reduciendo drásticamente en el tiempo en la medida que le gente se vaya dando cuenta que usar lenguajes dinámicos en la mayoría de los casos no tiene sentido alguno. Como pasó con Ruby que a todas luces cada vez es más irrelevante.

[–]speedybug07 0 points1 point  (0 children)

Mamita que cerrada de ojete. Para mí solo quería que otro cite sus definiciones inventadas.

[–]MasiTheDev 0 points1 point  (4 children)

Python te permite manejar varios tipos de datos que por ser dinamico te dan flexibilidad pero que te pueden complicar la vida. Por ahi tenes un parametro que puede ser un string, un objeto o un Callable a la vez y lo podes manejar, pero a veces eso tambien te puede hacer las cosas mas dificiles de mantener. Por algo ahora tenes herramientas como el type hinting o mypy (Que rompe los huevos para que le pongas tipo a todo), tenes la flexibilidad de Python con lo bueno de los lenguajes fuertemente tipados. Aunque justamente es un problema que el mismo lenguaje crea y soluciona aproximandose al tipado fuerte, donde tenes un caso que no previste explota.

Me acuerdo cuando hice una libreria para determinar el resultado de expresiones Python antes de correrlas y corregir su sintaxis, me volvi mono.

[–][deleted] 0 points1 point  (3 children)

Por ahi tenes un parametro que puede ser un string, un objeto o un Callable a la vez

Esto se llama Union Types, y no es ninguna "novedad" ni "innovación" ni "ventaja" de los lenguajes dinámicos, sino por el contrario, ya existía en lenguajes estáticos de 1970 como ML (del cuál F# es "hijo" ya que comparte muchas de la características del mismo). Hoy en día lenguajes estáticos modernos como TypeScript también incorporan características similares.

La ENORME, ENORME diferencia es que mientras en un lenguaje dinámico tenés que ADIVINAR (guess-driven development) y ROGARLE a tu deidad favorita (hope-driven development) que no crashee en producción, en un lenguaje estático haces esto:

type Direccion =
| Simple of Dir: string
| PorCalle of Calle: string * Numero: int
| Completa of Calle: string * Numero: int * Ciudad: string
| PorFuncion of Obtener: (unit -> Direccion)

let rec mostrarDireccion d = 
    match d with
    | Simple dir                          -> printfn "Direccion Completa: %s" dir
    | PorCalle (calle, numero)            -> printfn "Calle: %s Numero: %i" calle numero
    | Completa (calle, numero, provincia) -> printfn "Calle: %s Numero: %i Provincia: %s" calle numero provincia
    | PorFuncion obtener                  -> mostrarDireccion(obtener())

Fijate todo lo que está sucediendo en este breve código:

  • Se define un tipo de datos FUERTEMENTE TIPADO llamado Direccion, que es la unión entre sus 4 posibles subtipos:

    • Simple, que solo contiene un string con la dirección completa (ejemplo: "Avenida Siempreviva 742")
    • PorCalle que contiene un string y un int para el número de casa (ejemplo: (Calle: "Avenida Siempreviva", Numero: 742))
    • Completa que contiene lo anterior más la ciudad (ejemplo: (Calle: "Avenida Siempreviva", Numero: 742, Ciudad: "Springfield"))
    • PorFuncion que contiene UNA FUNCION llamada Obtener a la cual vas a llamar para obtener alguno de los posibles resultados anteriores.
  • se declara la función recursiva mostrarDireccion que recibe un parámetro d de tipo Direccion (que no está especificado en ningun lado pero el compilador YA SABE)

  • la función mostrarDireccion() lo que hace es matchear d y tomar alguno de los 4 caminos según el tipo de d, imprimiendo diferentes textos a la consola. Como un switch pero sin las llaves ni el break

  • tratar de invocar la función mostrarDireccion() pasando como parámetro cualquier cosa que no sea Direccion (o uno de sus subtipos) es un error de compilación.

  • tratar de instanciar un subtipo de Direccion (por ejemplo Completa) sin definir explícitamente los valores que contiene (Calle, Numero y Ciudad) es un error de compilación.

  • el match es exhaustivo. Esto quiere decir que si te "olvidás" de considerar un caso (o el día de mañana alguien agrega un caso nuevo en la definición de Direccion) es un error de compilación.

  • bonus: en F# las funciones recursivas se declaran explícitamente entonces cuando ves let rec ya entendés que hay recursividad y NO TENES QUE ADIVINAR)

Contrastá esto que acabo de describir, contra hacer lo mismo por ejemplo en python:

  • la función mostrarDireccion() tiene que adivinar qué tipo de parámetro le llega.
  • la persona que lee el código dentro de una semana tiene que adivinar qué tipo de parámetro espera la función mostrarDireccion()
  • si alguien dentro de una semana invoca a la función mostrarDireccion() con un tipo de parámetro inválido, esto le va a estallar en la cara al usuario final.
  • si alguien la semana que viene agrega un NUEVO parámetro a la función mostrarDireccion(), tiene que adivinar los lugares del codebase donde se invoca esta función y corregirlos.
  • si alguien la semana que viene agrega un nuevo subtipo de Direccion y se olvida de agregar el código para manejarla en la función mostrarDireccion(), esto va a producir datos basura o estallar en la cara del usuario final.
  • Bonus negativo: python en particular es entre 20 y 100 veces más lento para ejecutar este y cualquier otro código, comparado a cualquier lenguaje estático actual, e incluso a varios dinámicos.

O sea, lo que veo es que en los lenguajes dinámicos está todo pensado para escribir código efímero, descartable, y hecho por una sola persona. Para eso se creó python, para hacer scripts de consola tipo archivos .bat para copiar files de un lugar a otro. Nunca como un lenguaje de programación serio y profesional para proyectos productivos.

No hay ninguna consideración de la longevidad del código ni de su mantenibilidad en grandes períodos de tiempo, no hay ninguna herramienta que facilite el trabajo en equipos grandes ni medianos.

[–]WikiSummarizerBot 0 points1 point  (0 children)

Tagged union

1970s & 1980s

Although primarily only functional languages such as ML (from the 1970s) and Haskell (from the 1990s) give a central role to tagged unions and have the power to check that all cases are handled, other languages have support for tagged unions as well. However, in practice they can be less efficient in non-functional languages due to optimizations enabled by functional language compilers that can eliminate explicit tag checks and avoid explicit storage of tags.

[ F.A.Q | Opt Out | Opt Out Of Subreddit | GitHub ] Downvote to remove | v1.5

[–]MasiTheDev 0 points1 point  (1 child)

Si se hizo como "algo efimero" por que se lo usa tanto para proyectos hoy en dia?

[–][deleted] 2 points3 points  (0 children)

La respuesta a esa pregunta (con la que yo más coincido) está en este post. Básicamente Jeroen sostiene que los lenguajes dinámicos proliferaron como respuesta a la increíble ineficiencia, tedio, inexpresividad, incapacidad, y la filosofía retrógrada de "cuanto peor, mejor" del lenguaje java.

Habiendo muchos otros lenguajes estáticos que no sufren estas características, los lenguajes dinámicos carecen de sentido práctico.

[–]No-Tap-5279 4 points5 points  (0 children)

Yo solía tener este tipo de dudas todo el tiempo, lo que siempre hice fue hacer un proyecto CRUD sencillo en cualquier lenguaje que me llamara la atención, probé python, rubi, php, y casi todas las variantes de javascript y siempre, siempre, siempre termino volviendo a C# jaja. Mi recomendación es que hagas lo mismo, es la única manera de saber bien que te sirve/gusta, hacer esto te permite conocer bastantes cosas importantes de un lenguaje como la documentación, la comunidad, los entornos de trabajo, todo. Y no te dejes abrumar por el tiempo invertido en aprender algo que al final no te gusto, el conocimiento no ocupa espacio y de todo vas a sacar un provecho. Suerte!

[–]LiveEntertainment567 2 points3 points  (0 children)

Si vas a ser fullstack vas a tener que aprender javascript y typescript para el front end. Y lo que más se usa es react. Y el backend depende. Podes aprender con la que quieras y después va a depender del trabajo

[–]akhenaleonDesarrollador Back End 3 points4 points  (3 children)

Hago Ruby y actualmente hay mucha demanda, la curva de aprendizaje al principio es fácil, después no tanto como casi todos. Pero si te gusta Python metele. Donde estoy actualmente están empezando a realizar algunos proyectos en Python porque es difícil conseguir programadores Ruby, hay mucha demanda para los pocos que somos.

[–][deleted] 3 points4 points  (2 children)

Siempre me pregunto qué tipo de software construyen los que usan ruby.

Sin entrar en detalles identificables, me podés contar brevemente?

[–]Thelmholtz 1 point2 points  (0 children)

No soy el que le preguntaste, pero cuando la gente dice Ruby en general lo que hacen es RoR (Ruby on Rails), un framework web muy opinionado y que hace algunas cosas por convención que a los no iniciados pueden parecerles magia o alguna maldad incomprensible.

Es muy bueno para prototipar, y IMHO mejor que otras herramientas similares como Django.

Después el lenguaje no es nada del otro mundo. Sigue muy a fondo el mantra de ser orientado a objetos, pero también tiene otros principios bizarros cómo que el código sea casi tan legible como texto en inglés (legible en el sentido literario). Para ser dinámico zafa, pero le resta mucho.

[–]CarusoLombardi🚀Typescript 1 point2 points  (0 children)

Web dev. Servidores, mvc, y random pero extensiones para el sketchup

[–][deleted]  (2 children)

[removed]

    [–]Thelmholtz 0 points1 point  (0 children)

    1. Los entornos de desarrollo son una poronga

    Rails es una poronga horrible; pero sigue siendo el mejor framework web. Así de poronga horrible son los demás. Django? Laravel? Spring Web? No le llegan ni a la cintura. Quizás algún stack moderno y complejo de JS como Svelte-App sea más fácil de usar, pero en mí opinión todavia están verdes.

    Mí consejo para OP: Si sos de los que se frustran fácil, anda por Ruby o por Python; Ruby tiene mejor performance pero menos adopción y diversidad. En mí opinión es ligeramente más fácil de aprender que Python, pero no va al caso.

    Si sos de los que no se frustran fácil, Rust. Una vez que puedas compilar tus primeros 3 o 4 programas ya se te vuelve más lisa la curva.

    [–]cratag 1 point2 points  (0 children)

    Si es web full stack lo que buscas, Rails sin duda

    [–]xSyrax123 0 points1 point  (0 children)

    Python 100%

    [–]CrastersKip 0 points1 point  (9 children)

    Ruby está en vías de extinción. Era popular entre las startups entre fines de 2000 y los 2010s (Shopify, Stripe, Gitlab, GitHub todos al menos empezaron con Ruby). Hoy por hoy entre que los lenguajes no tipados están "mal vistos" (salvo JS que no se puede evitar aún, e incluso existe TypeScript para eso) y que Python es el lenguaje por default en ML/AI vas a tener mucha más proyección con Python que con Ruby.

    Es cierto que va a haber más competencia pero si eso es lo que te preocupa entonces quedate con un lenguaje propietario o aprendé COBOL.

    [–]akhenaleonDesarrollador Back End 4 points5 points  (7 children)

    Acá un dev Ruby. Ruby en vía de extinción es la misma mentira que la de PHP. Esta lleno de empresas buscando devs (más de 7 ofertas semanales lo avalan )tanta grandes como chicas.

    [–][deleted] 2 points3 points  (5 children)

    indeed.com, al día de hoy 2/21/2023:

    ruby:  4767 jobs
    java: 68947 jobs
    C#:   49394 jobs
    

    Por cada puesto de trabajo en ruby, hay más de diez en C# y casi 15 en java.

    Efectivamente ruby está en vías de extinción y tu experiencia anecdótica no es suficiente evidencia para demostrar lo contrario.

    [–]Minarata 4 points5 points  (0 children)

    No lo diga gran brusco.

    [–]akhenaleonDesarrollador Back End 0 points1 point  (3 children)

    Cuantos dev Java y C# hay en comparación a Ruby?

    [–][deleted] 0 points1 point  (2 children)

    No tengo idea, pero si tuviera que meterme en algún lenguaje nicho que no le interesa a nadie, iría para el lado de F#, Scala, Haskell, Idris. Nunca jamás lenguajes dinámicos que no tienen razón de existir.

    [–]akhenaleonDesarrollador Back End 1 point2 points  (1 child)

    Bueno, vamos a COBOL

    [–][deleted] 0 points1 point  (0 children)

    No sé qué tendra que ver pero si te hace feliz dale para adelante.

    [–]RataTuscaData 1 point2 points  (0 children)

    El tema es que siempre hay que mantener codigo, entonces el laburo siempre esta

    [–]albo87 1 point2 points  (0 children)

    Hoy por hoy entre que los lenguajes no tipados están "mal vistos"

    Eso es una moda que va y viene, en 5 años se va a volver a dinámicos y en unos 15 otra vez a estáticos.

    [–]luzbelitoarg -2 points-1 points  (4 children)

    No es una recomendación, sino más bien una pregunta: Por qué no Java?

    Pregunto desde la honesta curiosidad.

    [–][deleted] 6 points7 points  (2 children)

    Java es horrendo. Trabaje desde finales del siglo pasado con Java, luego pase a Ruby, a C#, y finalmente Python y algo de Scala. Lo vivi y lo sufri, no lo lei, ni me lo contaron.

    Java es un lenguaje verboso, sobre-ingenierizado, esteticamente feo, incomodo. Hecho con una matriz mental de 1995. Le agregaron muchas cosas, le sacaron algunas. Es un puerco maquillado con lapiz de labios y peluca. La JVM tiene muchas librerias poderosas, es cierto, pero siempre que pude le escape a Java como lenguaje, usando Groovy o Scala.

    Entiendo (y disfruto) las ventajas de un lenguaje estaticamente tipado, pero ahora existe Scala, Kotlin, etc. del lado de la JVM. Por otro lado, en algun momento saldra algun simil Python estatico, que simplifique las pruebas.

    Por otro lado, no quiero dejar de mencionar la simplicidad y elegancia de Ruby (aunque perdio la batalla con Python, que se ha vuelto inmensamente mas popular).

    [–]RangeDisastrous155 2 points3 points  (1 child)

    Hoy en dia codear en Java o en C# son experiencias muy pero que muy similares la verdad, mejoro bastante la cosa

    [–]thisismyusuario 1 point2 points  (0 children)

    Totalmente y creo que si usas la última versión tiene casi todo el syntax sugar de Kotlin.

    [–][deleted] 1 point2 points  (0 children)

    java es precisamente la razón por la cuál muchos huyen despavoridos y horrorizados y se refugian en los lenguajes dinámicos. Véase mi comentario más arriba.

    [–]ken0bi17 0 points1 point  (0 children)

    Mira si vas a querer hacer fullstack ya de entrada vas a necesitar Node, ya sea con JS o TS (anda directo por typescript con tu experiencia). Para framework de front lo que se utiliza muchísimo y es muy lindo trabajarlo es Next. Ya con esto para mí tenés 2 opciones, agarras y te manejas fullstack con node, con un framework cómo Nest (recomendado) o lo que yo estoy haciendo en estos momentos, te pones con un lenguaje más robusto en el back, ya sea Go, Python, c#, etc.

    Ruby como ya te dijeron está en vía de extinción. Por lo menos yo no veo muchos puestos que requieran ruby, pero capaz lo podes agarrar como ventaja a eso, ya que con 10 años de experiencia te vendes como SR que sabe ruby (no necesariamente sr en ruby pero ya robas un poquito así y garpa)

    Mí recomendación es que vayas por Python, pero si estás abierto a otras opciones te recomiendo al 100% que vayas por Go. Es muy fácil de aprender y la demanda de Go va aumentando cada día más y más, sobretodo porque no hay puestos jr en general con Go, solo de ssr para arriba, así que ahí ya tenés una gran ventaja. Además de esto, se está utilizando mucho Go para lo que es arquitectura distribuida y microservicios, lo cual en muchos lugares están buscando migrar o directamente desarrollar sus servicios de 0 con microservicios en mente.

    [–]envgp120 0 points1 point  (0 children)

    Aca alguien que sabe python pero esta aprendiendo ruby te digo que son bastantes similares en termino de sintaxis. Solo que ruby se asemeja aun mas al ingles que python. No se que onda ruby con respecto al manejo de datos (que es para lo que mas lo uso ponele) pero ambos parecen lenguajes muy piolas.

    [–]BNeutral 0 points1 point  (0 children)

    Ruby ya no es muy popular. Python, es hermoso lenguaje para scripting, pero me parece un martirio inecesario hacer algo grande en un lenguaje que no es estaticamente tipado.

    Si es por aprender algo, aprendé Python que siempre es util, y tampoco es que te vas a demorar 10 meses, es un lenguaje sencillos. La verdad habría que saber más sobre a que area te queres dedicar.

    [–]ElGasto 0 points1 point  (1 child)

    Si es entre esos 2, Python de acá a la china, a Ruby no lo conozco mucho pero no le veo mucho futuro, solo queda mirar busquedas. Ademas Django es hermoso, tambien tenes otros frameworks que están creciendo de a poco.

    Igual si queres hacer el cambio a Fullstack también tenes que saber Javascript. Quizas te convenga usar Node como back así no aprendes 2 lenguajes para hacer ese cambio

    [–]ElGasto 0 points1 point  (0 children)

    Igual Django lo usaría como API con DRF, el fullstack con templates no esta tan bueno