Translate

Mostrando las entradas con la etiqueta Pony. Mostrar todas las entradas
Mostrando las entradas con la etiqueta Pony. Mostrar todas las entradas

lunes, 2 de diciembre de 2024

Hola mundo en Pony


¡Comencemos a programar! Nuestro primer programa será uno muy tradicional. Vamos a imprimir “¡Hola, mundo!”. Primero, crea un directorio llamado helloworld:


mkdir helloworld

cd helloworld

¿Importa el nombre del directorio? Sí, importa. ¡Es el nombre de tu programa! De manera predeterminada, cuando tu programa es compilado, el binario ejecutable resultante tendrá el mismo nombre que el directorio en el que se encuentra tu programa. También puedes establecer el nombre usando las opciones –bin-name o -b en la línea de comandos.

Luego, crea un archivo en ese directorio llamado main.pony.

¿Importa el nombre del archivo? No para el compilador, no. A Pony no le importan los nombres de archivo, excepto que terminen en .pony. ¡Pero podría importarte a ti! Al darle buenos nombres a los archivos, puede ser más fácil encontrar el código que estás buscando más tarde.

En el archivo, pongamos el siguiente código:


actor Main

    new create(env: Env) =>

    env.out.print("¡Hola, mundo!")



Ahora compílarlo:


$ ponyc

Building .

Building builtin

Generating

Optimising

Writing ./helloworld.o

Linking ./helloworld


¡Mira eso! Compiló el directorio actual, ., más las cosas que están incorporadas en Pony, builtin, generó algo de código, lo optimizó, creó un archivo de objeto (no te preocupes si no sabes qué es eso) y lo vinculó a un ejecutable con las bibliotecas que se necesitaban. Si eres un programador de C/C++, todo esto tendrá sentido para ti, de lo contrario, probablemente no lo tenga, pero no importa, puedes ignorarlo.

Espera, ¿también se vinculó? Sí. No necesitarás un sistema de compilación (como make) para Pony. Se encarga de eso por ti (incluso de manejar el orden de las dependencias cuando te vinculas a bibliotecas de C, pero llegaremos a eso más adelante).


Ahora podemos ejecutar el programa:


$ ./helloworld

¡Hola, mundo!

¡Felicitaciones, hemos escrito nuestro primer programa Pony! 

sábado, 23 de noviembre de 2024

La filosofía Ponylang: "hacer las cosas bien"


En el espíritu de Richard Gabriel, la filosofía Pony no es ni “lo correcto” ni “lo peor es mejor”. Es “hacer las cosas bien”.

  • Corrección. La incorrección simplemente no está permitida. No tiene sentido intentar hacer las cosas si no puedes garantizar que el resultado sea correcto.
  • Rendimiento. La velocidad en tiempo de ejecución es más importante que todo excepto la corrección. Si se debe sacrificar el rendimiento por la corrección, intenta encontrar una nueva forma de hacer las cosas. Cuanto más rápido pueda el programa hacer las cosas, mejor. Esto es más importante que cualquier cosa excepto un resultado correcto.
  • Simplicidad. La simplicidad se puede sacrificar por el rendimiento. Es más importante que la interfaz sea simple que la implementación. Cuanto más rápido pueda el programador hacer las cosas, mejor. Está bien hacer las cosas un poco más difíciles para el programador para mejorar el rendimiento, pero es más importante hacer las cosas más fáciles para el programador que para el lenguaje/tiempo de ejecución.
  • Coherencia. La consistencia puede sacrificarse por la simplicidad o el rendimiento. No permita que una consistencia excesiva se interponga en el camino de hacer las cosas.
  • Completitud. Es bueno cubrir tantas cosas como sea posible, pero la completitud puede sacrificarse por cualquier otra cosa. Es mejor hacer algunas cosas ahora que esperar hasta que todo pueda hacerse más tarde.

El enfoque de "hacer las cosas" tiene la misma actitud hacia la corrección y la simplicidad que "lo correcto", pero la misma actitud hacia la consistencia y la completitud que "lo peor es mejor". También agrega el rendimiento como un nuevo principio, tratándolo como la segunda cosa más importante (después de la corrección).

A lo largo del diseño y desarrollo del lenguaje se deben respetar los siguientes principios.

  • Utilice el enfoque de hacer las cosas.
  • Gramática simple. El lenguaje debe ser trivial de analizar tanto para humanos como para computadoras.
  • Sin código cargable. Todo es conocido por el compilador.
  • Totalmente seguro para los tipos. No existe la coerción del tipo “confía en mí, sé lo que estoy haciendo”.
  • Totalmente seguro para la memoria. No existe la coerción del tipo “este número aleatorio es en realidad un puntero, de verdad”.
  • No hay fallos. Un programa que compila nunca debería fallar (aunque puede quedarse colgado o hacer algo no deseado).
  • Mensajes de error sensatos. Siempre que sea posible, utilice mensajes de error simples para casos de error específicos. Está bien asumir que el programador conoce las definiciones de las palabras en nuestro léxico, pero evite la jerga de compiladores u otra jerga informática.
  • Sistema de compilación inherente. No se requieren aplicaciones separadas para configurar o compilar.
  • Trate de reducir los errores de programación comunes mediante el uso de una sintaxis restrictiva.
  • Proporcione una forma única, limpia y clara de hacer las cosas en lugar de atender los prejuicios preferidos de cada programador.
  • Realice actualizaciones limpias. No intente fusionar las nuevas características con las que están reemplazando, si algo está roto, elimínelo y reemplácelo de una sola vez. Siempre que sea posible, proporcione utilidades de reescritura para actualizar el código fuente entre versiones de lenguaje.
  • Tiempo de compilación razonable. Reducir el tiempo de compilación es importante, pero menos importante que el rendimiento y la corrección en tiempo de ejecución.
  • Está bien permitir que el programador omita algunas cosas del código (argumentos predeterminados, inferencia de tipos, etc.), pero siempre se debe permitir la especificación completa.
  • Sin ambigüedad. El programador nunca debería tener que adivinar lo que hará el compilador, o viceversa.
  • Documentar la complejidad requerida. No todas las características del lenguaje tienen que ser triviales de entender, pero las características complejas deben tener explicaciones completas en la documentación para que se permitan en el lenguaje.
  • Las características del lenguaje deben ser mínimamente intrusivas cuando no se usan.
  • Semántica completamente definida. La semántica de todas las características del lenguaje debe estar disponible en la documentación estándar del lenguaje. No es aceptable dejar el comportamiento sin definir o "dependiente de la implementación".
  • Debe estar disponible un acceso eficiente al hardware, pero esto no tiene que impregnar todo el lenguaje.
  • La biblioteca estándar debe implementarse en Pony.
  • Interoperabilidad. Debe ser interoperable con otros lenguajes, pero esto puede requerir una capa de corrección si se utilizan tipos no primitivos.
  • Evite problemas con la biblioteca. El uso de bibliotecas Pony de terceros debe ser lo más sencillo posible, sin sorpresas. Esto incluye escribir y distribuir bibliotecas y usar múltiples versiones de una biblioteca en un solo programa.

martes, 19 de noviembre de 2024

QuickSort en Pony


Un Algoritmo que me gusta mucho es el quicksort, porque es un algoritmo por demás claro. Ya he escrito lo fácil que es implementarlo en scala, erlang, rust, haskell , F# y lisp.

Ahora le toca a Pony. Básicamente el algoritmo toma un pivot y agrupa los menores del pivot al principio y los mayores al final y aplica quicksort a estos 2 grupos. Y si la lista es vacía o tiene un elemento, ya esta ordenada. 


Vamos al código:  


 actor Main

  new create(env: Env) =>

    let data = [4; 2; 7; 1; 3; 6; 5]

    env.out.print("Original: " + data.string())


    let sorted = quicksort(data)

    env.out.print("Sorted: " + sorted.string())


  fun quicksort(data: Array[U64]): Array[U64] =>

    if data.size() <= 1 then

      data

    else

      let pivot = data(0)?

      let less = data.values().filter(lambda(x: U64): Bool => x < pivot end)

      let greater = data.values().filter(lambda(x: U64): Bool => x > pivot end)


      let less_sorted = quicksort(less)

      let greater_sorted = quicksort(greater)


      let result = less_sorted.append(pivot)

      result.append(greater_sorted)

    end


sábado, 16 de noviembre de 2024

Primeros pasos en Pony


Pony es un lenguaje de programación orientado a objetos, actor-modelo, capacidades seguras. Es orientado a objetos porque tiene clases y objetos, como Python, Java, C++ y muchos otros lenguajes. Es actor-modelo porque tiene actores (similares a Erlang, Elixir o Akka). Estos se comportan como objetos, pero también pueden ejecutar código de forma asincrónica. Los actores hacen que Pony sea increíble.

Cuando decimos que Pony es seguro en cuanto a capacidades, nos referimos a algunas cosas:

  • Es seguro en cuanto a tipos. Realmente seguro en cuanto a tipos. 
  • Es seguro en cuanto a memoria. Esto viene con seguridad en cuanto a tipos, pero sigue siendo interesante. No hay punteros, ni desbordamientos de búfer, ni siquiera tiene el concepto de nulo.
  • Es seguro en cuanto a excepciones. No hay excepciones en tiempo de ejecución. Todas las “situaciones excepcionales” tienen una semántica definida y siempre se manejan.
  • No tiene carreras de datos. Pony no tiene bloqueos ni operaciones atómicas ni nada parecido. En cambio, el sistema de tipos garantiza en tiempo de compilación que su programa concurrente nunca pueda tener carreras de datos. Así que puede escribir código altamente concurrente y nunca equivocarse.
  • No tiene interbloqueos. Esto es fácil, Pony no tiene bloqueos en absoluto. Así que definitivamente no se bloquean, porque no existen.

Pony no puede impedir que se escriba errores lógicos, pero puede evitar que clases enteras de errores sean posibles. El compilador Pony evita que accedas a la memoria de forma insegura de forma concurrente. Si alguna vez has hecho programación concurrente, sabes lo difícil que puede ser rastrear este tipo de cosas. 

domingo, 10 de noviembre de 2024

Pony: Un Lenguaje de Programación basado en actores

 


En un mundo donde la concurrencia y el rendimiento son esenciales, el lenguaje de programación Pony emerge como una solución innovadora que permite escribir aplicaciones concurrentes de manera segura y eficiente. Pony combina paradigmas de actor y tipos de referencia para manejar múltiples tareas sin necesidad de bloqueos ni condiciones de carrera. 

Pony es un lenguaje de programación orientado a actores, diseñado para ofrecer concurrencia segura sin caer en los problemas típicos de bloqueos y condiciones de carrera. Fue creado por Sylvan Clebsch y otros investigadores de la Universidad de Cambridge y se enfoca en aplicaciones que requieren alta concurrencia y bajo tiempo de respuesta.

Algunas características clave de Pony incluyen:

- Concurrencia sin bloqueos: Pony utiliza un sistema de tipos de referencia que garantiza que el código concurrente no genere condiciones de carrera.

- Recolección de basura libre de pausas: Su recolección de basura está diseñada para ser concurrente y no requiere detener la ejecución de los programas.

- Orientación a actores: Al igual que Elixir y Erlang, Pony usa actores como unidades de concurrencia.

El sistema de tipos de referencia en Pony es lo que permite su concurrencia segura. Existen cinco tipos de referencia principales en Pony:

  • iso: Garantiza que solo hay una referencia a un valor.
  • rn: Representa una referencia transitoria que puede transferirse entre actores.
  • val: Un valor inmutable que puede ser compartido de manera segura.
  • ref: Una referencia mutable exclusiva de un actor.
  • box: Una referencia de solo lectura.

Al definir el tipo de referencia de cada variable, Pony asegura que los datos compartidos entre actores no puedan ser modificados de manera insegura.

Aquí tienes un ejemplo básico que demuestra el uso de actores en Pony. En este ejemplo, crearemos un actor llamado `Counter` que cuenta hasta un valor especificado y luego envía un mensaje de notificación.


actor Counter

  var count: U32

  var target: U32

  let notify: Notifier


  new create(target: U32, notify: Notifier) =>

    count = 0

    this.target = target

    this.notify = notify


  be increment() =>

    count = count + 1

    if count >= target then

      notify.done()

    end

end


actor Notifier

  be done() =>

    @println[I32]("Contador alcanzó el objetivo!".cstring())


En este código:

  1. El actor Counter tiene una función increment que aumenta el contador.
  2. Cuando el contador llega al objetivo, se llama al método done del actor Notifier.


Pony es un lenguaje único en el ecosistema de lenguajes concurrentes. Con su sistema de tipos de referencia y su enfoque en actores, Pony proporciona un marco robusto para aplicaciones concurrentes y distribuidas. Aunque es relativamente nuevo, su propuesta de concurrencia segura y recolección de basura eficiente lo convierten en una opción interesante para desarrolladores que buscan maximizar el rendimiento sin comprometer la seguridad.

Dejo link: https://www.ponylang.io/