domingo, 13 de octubre de 2024

¿De qué trata esProc SPL?

esProc SPL es un lenguaje de procesamiento y cálculo de datos.

  • Se ejecuta como una base de datos de análisis o middleware.
  • Útil para cálculo y procesamiento de datos estructurados y semiestructurados. Ofrece un rendimiento superior y es ideal para tareas con uso intensivo de datos en el entorno impulsado por datos actual. 
  • Útil para trabajo por lotes sin conexión, consulta en línea.
  • Ni sistema SQL ni tecnología NoSQL. Trabaja directamente sobre los datos.
  • Con sintaxis SPL de creación propia, más concisa y eficiente SPL: Lenguaje de proceso estructurado.

En conclusión, esProc SPL está diseñado para el procesamiento avanzado de datos y se destaca en el manejo eficiente de conjuntos de datos masivos.

Los sitios oficiales del lenguaje son:

Si quieres aprenderlo, puedes revisar la documentación oficial:

https://www.scudata.com/html/SPL-programming-book.html

Al iniciar la aplicación, se abre un grid similar a las hojas de Excel. Es aquí donde se escribe el código:

Escribimos el código o instrucciones de manera similar a lo que se hace en Excel:

=2*1.5
=1*(2+3)
=65536*65536*65536*65536
=1*(2-3*(4+5))

Se pueden operar con tipos de datos Integer, Float, Long, etc. Además de también realizar operaciones booleanas (que dan resultados TRUE o FALSE). Hacer uso de sentencias de control para los bucles o condiciones a cumplir en el programa (for, ).

=if(x>0,x,-x)
=if(x>y,x,y)

!true = false
!false = true

=A1*A1*A1
>A1=B1

for 20

=[3,9,0,2,2.3,9.8]

if B1<=100

Podemos concluir en que esProc SPL es un lenguaje de script para procesamiento de datos, con funciones de biblioteca ricas y bien diseñadas y una sintaxis poderosa, que puede ejecutarse en un programa Java a través de la interfaz JDBC y computarse de forma independiente.

Continuaremos en próximas entregas.

Enlaces:

https://dev.to/bigsondev/10-programming-languages-worth-learning-in-2024-afa
https://github.com/SPLWare/esProc
https://www.scudata.com/
https://www.reddit.com/r/esProc_SPL/
https://www.scudata.com/html/SPL-programming-book.html

sábado, 5 de octubre de 2024

Gleam en ejemplos

Continuamos con el tema de Gleam, un lenguaje que corre sobre la máquina virtual de Erlang (BEAM). Similar a Elixir en algunos aspectos.

Si quieres programar usando este lenguaje y además usas VsCode como editor, existe un plugin que podrás instalar:

https://marketplace.visualstudio.com/items?itemName=Gleam.gleam

Te ayudará en el resaltado de estilo, formato, definición y autocompletado.

Recordemos cómo crear un proyecto en Gleam:

gleam new proyecto

Nos ubicamos en el directorio creado:

cd proyecto

Podemos usar VsCode. Abrimos una terminal y tecleamos:

code .

Esto abrirá el editor de código.

Ejemplo 1. Crear una función que mande un saludo.

La sintaxis para crear una función es la siguiente:

pub fn nombre_funcion() {
  // Cuerpo del procedimiento o función
}

Nuestra función será esta:

pub fn saludo() {
  io.println("\t Hola, mundo desde Gleam")
}

La invocamos desde el método main del programa principal.

proyecto.gleam

import gleam/io

pub fn main() {
  saludo()
}

pub fn saludo() {
  io.println("\t Hola, mundo desde Gleam")
}

Construimos y ejecutamos:

gleam build
gleam run

Salida:

        Hola, mundo desde Gleam

Ejemplo 2. Crear una función que calcula el factorial de un número.

Teniendo el siguiente pseudo código:

numero = 5
IF numero = 0 THEN
   result = 1
IF ELSE numero = 1 THEN
   result = 1
ELSE 
   result = numero * FACTORIAL(numero - 1)

La función en Gleam quedaría de tal modo:

pub fn factorial(x: Int) -> Int {
  case x {
    0 -> 1
    1 -> 1
    _ -> x * factorial(x - 1)
  }
}

La invocamos de esta manera:

import gleam/io
import gleam/int

pub fn main() {
  io.println("\t===== Factorial en Gleam =====")
  io.println("El factorial de 5: ")
  io.debug(factorial(5))
  io.println("El factorial de 7: ")
  io.debug(factorial(7))
}

Ejemplo 3. Crear una función anónima que sume dos número enteros.

fn suma(a: Int, b: Int) -> Int {
  a + b
}

Y la invocamos de la siguiente forma:

import gleam/io
import gleam/int


pub fn main() {
  io.println("\t===== Sumando en Gleam =====")
  let add = suma(3, 4)
  io.println("Suma (3,4) es: ")
  io.debug(add)
}

Este post se irá actualizando para agregar más ejemplos.

Enlaces:

https://codemonkeyjunior.blogspot.com/2024/03/conociendo-gleam-un-lenguaje-que-corre.html
https://emanuelpeg.blogspot.com/search?q=gleam

sábado, 7 de septiembre de 2024

Crystal, un lenguaje de programación similar a Ruby

Crystal es un digno "copycat" del lenguje de programación Ruby. Su sintaxis es más que similar.

cadena = "Codemonkey Junior"
puts cadena

Y es que escribir unas cuantas líneas en este lenguaje nos recuerda a Ruby. Crystal es de esos lenguajes que deberías aprender o echar un vistazo, al menos por curiosidad.

Para instalarlo deberás entrar a este sitio y escoger la instalación de acuerdo a tu SO:

https://crystal-lang.org/install/

Una vez instalado, abre una terminal y teclea:

crystal --version

Eso listará la versión instalada.

Empezaremos con el clásico programa de "Hola, mundo".

holamundo.cr

puts "Hola, mundo!!"

Ejecutamos:

crystal holamundo.cr

Salida:

Hola, mundo!!

Sigamos con otro ejemplo. Mostremos algunas variables en Crystal.

variables.cr

# Variables en Crystal
entero = 0
caracter = '\u0032'
booleano = true
real = 9.32
 
puts "#{entero}"
puts "#{caracter}"
puts "#{real}"
 
if booleano
    puts "Es verdadero"
end

Ejecutar:

crystal variables.cr

Salida:

0
2
9.32
Es verdadero

¡Hemos creado nuestros primeros programas en Crystal!

Continuaremos con este tema más adelante.

Enlaces:

https://crystal-lang.org/

sábado, 31 de agosto de 2024

Sinatra, un DSL útil para crear sitios web de manera rápida

Sinatra es una herramienta que toma su nombre del famoso cantante estadounidense. Similar a otras herramientas como Flask (salvando las diferencias, claro esta). Con la peculiaridad que esta diseñado para el lenguaje de programación Ruby.

¿Qué haremos?

  1. Instalar Ruby.
  2. Instalar Sinatra.
  3. Crear un proyecto sencillo con Sinatra.

Una vez instalado Ruby podemos comprobar la instalación:

ruby --version

Instalamos Sinatra y Rackup:

gem install sinatra
gem install rackup

También podemos instalar Puma (opcional):

gem install puma

Para ver nuestras "gemas" instaladas, basta con ubicarnos en esta carpeta (gem):

C:\Users\HP\.local\share\gem\ruby\3.3.0\gems

Creamos un programa llamado ``myapp.rb``. El cual tendrá lo siguiente:

# myapp.rb
require 'sinatra'

get '/' do
  'Hola, mundo!'
end

Ejecutamos la aplicación:

ruby myapp.rb

Si todo es correcto, veremos un mensaje de "Hola, mundo!" en la dirección http://[::1]:4567 o http://localhost:4567

¡Hemos creado nuestra primera aplicación con Sinatra!

En próximas entregas continuaremos con este tema.

Enlaces:

https://sinatrarb.com/
https://www.ruby-lang.org/es/
https://rubyinstaller.org/
https://crguezl.github.io/apuntes-ruby/node409.html

sábado, 10 de agosto de 2024

GCP: Calculando el IMC con BigQuery

 


En esta ocasión veremos cómo crear una función y procedimiento almacenado para el cálculo del IMC (Índice de Masa Corporal), necesitaremos lo siguiente:

  1. La fórmula para el cálculo del IMC.
  2. Crear una función para calcularlo.
  3. Crear un procedimiento almacenado (stored procedure) para usar la función.
  4. Crear un bloque de código en BigQuery para invocar el procedimiento. 

Tenemos la fórmula:

-- Obtener IMC
IMC = p/(t*t)

Donde:
p= peso
t= talla o estatura
imc = el índice de masa corporal

Creando función para calcular el IMC:

CREATE OR REPLACE FUNCTION `myproject.dataset.imcCalculo`(peso NUMERIC, talla NUMERIC)
RETURNS NUMERIC AS(
  (peso/(talla*talla))
);

Básicamente es una operación sencilla que solo incluye una multiplicación de la talla y la división del peso.

Creando procedimiento almacenado para invocar la función:

CREATE OR REPLACE PROCEDURE `myproject.dataset.getIMC`(peso NUMERIC, talla NUMERIC, OUT msg STRING)
BEGIN 
  DECLARE imc NUMERIC DEFAULT 0.0;
  
  set msg = 'Iniciamos calculo. ';
  SET imc = (SELECT `myproject.dataset.imcCalculo`(peso, talla));
  set msg = concat(msg, 'El IMC es: ', imc, '. Resultado: ');
  set msg = concat(msg, (  
    CASE imc
    WHEN imc<=16.0 OR imc<=16.99 THEN 'Delgadez moderada.'
    WHEN imc<=17.0 OR imc<=18.49 THEN 'Delgadez aceptable.'
    WHEN imc<=18.50 OR imc<=24.99 THEN 'Peso normal.'
    WHEN imc<=25.0 OR imc<=29.99 THEN 'Sobrepeso.'
    WHEN imc<=30.0 OR imc<=34.99 THEN 'Obeso tipo I.'
    WHEN imc<=35.0 OR imc<=40.0 THEN 'Obeso tipo II.'
    ELSE 'No existe clasificacion'
    END)
  );
  
  
  SELECT msg;
  

END;

En el procedimiento almacenado incluimos un mensaje de salida (OUT msg STRING) el cual podrá ser consultado al finalizar el llamado. Este contendrá el cálculo del IMC y el diagnóstico final (peso normal, sobrepeso, etc.).

Creando bloque de BigQuery para invocar procedimiento almacenado:

-- Obtener IMC
BEGIN  
DECLARE peso NUMERIC DEFAULT 56.0;
DECLARE talla NUMERIC DEFAULT 1.65;
DECLARE msg STRING DEFAULT 'Inicio';

CALL `myproject.dataset.getIMC`(peso, talla, msg);
SELECT msg;

END;

Usar un bloque nos ayuda a disminuir una cantidad "grosera" de sentencias.

El resultado de la operación nos dará como resultado: 20.5693. La salida será:

Iniciamos calculo. El IMC es:  20.569329. Resultado: Peso normal.

Crear funciones y procedimientos almacenados es algo muy útil y que nos ahorrará trabajo.

Enlaces:

https://cloud.google.com/bigquery/docs/reference/standard-sql/conditional_expressions
https://codemonkeyjunior.blogspot.com/2024/08/gcp-cargar-y-exportar-datos-en-bigquery.html

https://lineadecodigo.com/java/calcular-el-indice-de-masa-corporal-con-java/
https://codemonkeyjunior.blogspot.com/2013/05/programando-en-ceylon-no1_13.html

sábado, 3 de agosto de 2024

GCP: Cargar y exportar datos en BigQuery


GCP BigQuery nos permite tanto cargar como exportar datos. Los formatos de los archivos pueden ser TXT o CSV generalmente.

Si queremos exportar datos de una tabla a un archivo CSV podríamos hacer los siguiente.

Abrimos la consola de GCP y en el editor de consultas colocamos:

EXPORT DATA
  OPTIONS (
    uri = 'gs://bucket/folder/pesos*.csv',
    format = 'CSV',
    overwrite = true,
    header = true,
    field_delimiter = ';')
AS (
  SELECT fecha, valor
  FROM mydataset.pesos
  ORDER BY fecha
);

Como se puede ver:

  1. Colocamos la ubicación de nuestro Bucket.
  2. Seteamos el formato del archivo, en este caso será un CSV.
  3. El archivo será sobreescrito.
  4. El delimitardor será un punto y coma (;).

Una vez que el comando es ejecutado desde el editor de consultas GCP, debemos uicarnos en el directorio y descargar el archivo CSV generado.

Si queremos complicarnos la vida, podríamos crear un programa en Java que haga exactamente los mismo.

ExtractTableToCsv.java

import com.google.cloud.RetryOption;
import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.Table;
import com.google.cloud.bigquery.TableId;
import org.threeten.bp.Duration;

public class ExtractTableToCsv {

  public static void runExtractTableToCsv() {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "bigquery-public-data";
    String datasetName = "samples";
    String tableName = "shakespeare";
    String bucketName = "my-bucket";
    String destinationUri = "gs://" + bucketName + "/path/to/file";
    // For more information on export formats available see:
    // https://cloud.google.com/bigquery/docs/exporting-data#export_formats_and_compression_types
    // For more information on Job see:
    // https://googleapis.dev/java/google-cloud-clients/latest/index.html?com/google/cloud/bigquery/package-summary.html

    String dataFormat = "CSV";
    extractTableToCsv(projectId, datasetName, tableName, destinationUri, dataFormat);
  }

  // Exports datasetName:tableName to destinationUri as raw CSV
  public static void extractTableToCsv(
      String projectId,
      String datasetName,
      String tableName,
      String destinationUri,
      String dataFormat) {
    try {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

      TableId tableId = TableId.of(projectId, datasetName, tableName);
      Table table = bigquery.getTable(tableId);

      Job job = table.extract(dataFormat, destinationUri);

      // Blocks until this job completes its execution, either failing or succeeding.
      Job completedJob =
          job.waitFor(
              RetryOption.initialRetryDelay(Duration.ofSeconds(1)),
              RetryOption.totalTimeout(Duration.ofMinutes(3)));
      if (completedJob == null) {
        System.out.println("Job not executed since it no longer exists.");
        return;
      } else if (completedJob.getStatus().getError() != null) {
        System.out.println(
            "BigQuery was unable to extract due to an error: \n" + job.getStatus().getError());
        return;
      }
      System.out.println(
          "Table export successful. Check in GCS bucket for the " + dataFormat + " file.");
    } catch (BigQueryException | InterruptedException e) {
      System.out.println("Table extraction job was interrupted. \n" + e.toString());
    }
  }
}

Ahora, ¿si queremos cargar un archivo a una determinada tabla?

Procedemos a escribir la siguiente instrucción en el editor de consultas de GCP:

LOAD DATA INTO mydataset.pesos FROM FILES(
  format = 'CSV',
  uri = ['gs://bucket/folder/123.csv','gs://bucket/folder/456.csv']
);

Donde:

  1. Definimos el formato de los archivos a cargar, en este caso son CSV.
  2. Colocamos la ubicación de los archivos de datos a cargar en la tabla (pesos).

Nota: El archivo CSV debe contener campos que concuerden con los de la tabla. En caso contrario, habrá errores a la hora de la carga.

Si queremos complicarnos la vida, podríamos crear un programa en Java que haga exactamente los mismo.

LoadCsvFromGcs.java

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.CsvOptions;
import com.google.cloud.bigquery.Field;
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.JobInfo;
import com.google.cloud.bigquery.LoadJobConfiguration;
import com.google.cloud.bigquery.Schema;
import com.google.cloud.bigquery.StandardSQLTypeName;
import com.google.cloud.bigquery.TableId;

// Sample to load CSV data from Cloud Storage into a new BigQuery table
public class LoadCsvFromGcs {

  public static void runLoadCsvFromGcs() throws Exception {
    // TODO(developer): Replace these variables before running the sample.
    String datasetName = "MY_DATASET_NAME";
    String tableName = "MY_TABLE_NAME";
    String sourceUri = "gs://cloud-samples-data/bigquery/us-states/us-states.csv";
    Schema schema =
        Schema.of(
            Field.of("name", StandardSQLTypeName.STRING),
            Field.of("post_abbr", StandardSQLTypeName.STRING));
    loadCsvFromGcs(datasetName, tableName, sourceUri, schema);
  }

  public static void loadCsvFromGcs(
      String datasetName, String tableName, String sourceUri, Schema schema) {
    try {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

      // Skip header row in the file.
      CsvOptions csvOptions = CsvOptions.newBuilder().setSkipLeadingRows(1).build();

      TableId tableId = TableId.of(datasetName, tableName);
      LoadJobConfiguration loadConfig =
          LoadJobConfiguration.newBuilder(tableId, sourceUri, csvOptions).setSchema(schema).build();

      // Load data from a GCS CSV file into the table
      Job job = bigquery.create(JobInfo.of(loadConfig));
      // Blocks until this load table job completes its execution, either failing or succeeding.
      job = job.waitFor();
      if (job.isDone()) {
        System.out.println("CSV from GCS successfully added during load append job");
      } else {
        System.out.println(
            "BigQuery was unable to load into the table due to an error:"
                + job.getStatus().getError());
      }
    } catch (BigQueryException | InterruptedException e) {
      System.out.println("Column not added during load append \n" + e.toString());
    }
  }
}

Nota: El código se tomó de la página oficial de GCP. Tu lo puedes editar a tu conveniencia.

Hemos visto como cargar y exportar datos a tablas en BigQuery.

Enlaces:

https://cloud.google.com/bigquery/docs/exporting-data
https://cloud.google.com/bigquery/docs/loading-data-cloud-storage-csv

F#: un lenguaje funcional

F# (Efe sharp) es un lenguaje de paradigma funcional desarrollado por (la malévola empresa) Microsoft.

Presume de una simplicidad y facilidad para ser aprendido (y usado).

A primera vista nos recuerda a lenguajes como Powershell, Javascript, Perl, Python o Ruby.

F# tiene una sintaxis ligera que requiere muy poco código para compilar software.

Está respaldado por un sistema de tipos eficaz, una biblioteca estándar cómoda y un entorno de ejecución de .NET en el que puede confiar para crear software crítico que sea correcto, rápido y confiable.

La extensión de un programa en F# puede ser *.fs o *.fsx.

Si no tienes instalado Dotnet ve este sitio:

https://dotnet.microsoft.com/en-us/download

Al tenerlo ya instalado, te permitirá crear programas y aplicaciones F#.

Escribamos el clásico "Hola, mundo" en este lenguaje:

holamundo.fsx

printfn "Hola, mundo!!"

Para ejecutar podemos usar dotnet:

dotnet fsi holamundo.fsx

Salida:

Hola, mundo!!

Crear un proyecto F#

Para crear un proyecto F# deberás teclear esto:

dotnet new console --language F#
dotnet run

Se generará un proyecto F# y se ejecutará.

Variables en F#

F# es un lenguaje fuertemente tipado que utiliza inferencia de tipos (int, float, string, bool, etc.). Por lo que deberás cuidar el tipo de dato a declarar. Aunque existe la inferencia de tipos en caso de que no quieras definir el tipo.

variables.fs

// Tipos de datos
let numeroEntero = 23
let (numerico: int) = 32
let (cadena: string) = "FERROCARRILERO"
let (isOk: bool) = true
let real = 90.43

Hemos declarado algunas variables y definido sus tipos. Imprimiremos sus valores de la siguiente forma:

printfn "numeroEntero: %i" numeroEntero
printfn "numerico: %i" numerico
printfn "cadena: %s" cadena
printfn "isOk: %b" isOk
printfn "real: %f" real

Tambien podemos introducir datos, usando las liberías de .Net

entrada.fs

open System

printfn "Introduce tu nombre:"
let nombre = Console.ReadLine()
printfn "Hola, %s" nombre

Ejecutamos (dotnet run):

Introduce tu nombre:
Thomas Muller
Hola, Thomas Muller

En F# todas las variables son inmutables, es decir, no cambian de valor. Si requieres que una variable cambie su valor deberás usar la palabra ``mutable``, esto similar a lenguajes como Rust.

// Variables mutables
let mutable contador = 0
printfn "Contador: %i" contador
contador <- 1
printfn "Contador: %i" contador 

Esto es todo por hoy. En próximas entregas continuaremos con este tema.

Enlaces:

https://fsharp.org/
Vídeos sobre F#
https://es.wikipedia.org/wiki/F_Sharp
https://dotnet.microsoft.com/en-us/learn/dotnet/in-browser-tutorial/1