/JOLC

Primary LanguageJulia

JOLC

Julia es un lenguaje de programación bastante reciente que le interesa a científicos de datos, estadísticos y analistas financieros. Este cuenta con distintas características atractivas para los programadores. Aún así, Julia al ser un lenguaje de programación bastante reciente, hay muy pocos lugares donde se pueda probar su sintaxis de manera sencilla. Es por eso que se desarrollo JOLC, un lenguaje de programación basado en Julia que se podrá programar desde el navegador.

A continuación, se detalla la sintaxis que tendrá JOLC. Además de algunos archivos de entrada de prueba que podrán probar para familiarizarse con la sintaxis.

Tabla de Contenido

  1. Comentarios
  2. Tipos
  3. Expresiones
  4. Instrucciones
    1. Impresión
    2. Declaración y Asignación
    3. Llamada a Funciones
    4. Distintas Funciones Nativas
    5. Funciones
    6. Condicionales
    7. Loops
      1. While
      2. For
    8. Arreglos
    9. Structs

Comentarios

Los comentarios pueden ser:

  • Una línea (#)
  • Múltiples líneas (#= ... =#)
    # Esto es un comentario de una sola línea

    #=
        Esto es un
        comentario de
        múltiples líneas
    =#

Tipos

JOLC aceptará distintos tipos de datos con los que cuenta Julia. Entre ellos se aceptarán:

Nulo:

Se representa con la palabra reservada Nothing, la cual indica que no existe ningún valor.

Int64

Valores numéricos enteros. Por ejemplo: 3, 2, -1, -100.

Float64

Valores númericos con punto flotante. Por ejemplo: 3.1415, 2.7182, 0.5.

Bool

Los valores booleanos únicamente pueden ser true o false.

Char

Estos son literales de carateres, se definen con comillas simples. Por ejemplo: 'a', 'b', 'z'.

String

Estos representan cadenas de texto, se definen con comillas dobles. Por ejemplo: "Hola", "Mundo", "!".

Los Strings también cuentan con operaciones especiales que se pueden realizar con estos. Se detalla más adelante en la sección de Expresiones.

Arreglos

Estos son un conjunto de valores indexados entre 1 hasta n, que pueden ser de diferentes tipos. Por ejemplo:

[10, 20, 30, 40]
["Hola", "Mundo"]
['a', 2.0, 5, ["Hola", "Mundo"]].

Los arreglos cuentan con distintas operaciones que se detallarán en la sección de Arreglos.

Struct

Estos son tipos compuestos definidos por el programador. Existen 2 tipos de Struct, aquellos que son mutables y los inmutables. Para la declaración de struct inmutables se realizar de la siguiente manera:

struct NOMBRE_STRUCT
    LISTA_ATRIBUTOS
end;

Para declarar un Struct mutable se agrega la palabra reservada mutable:

mutable struct NOMBRE_STRUCT
    LISTA_ATRIBUTOS
end;

Y para crear una variable con nuestro Struct, se escribe:

ID = NOMBRE_STRUCT(LISTA_VALORES);

Un ejemplo de creación de struct podría ser:

struct Rectangulo
    base::Int64;
    altura;
end;

Noten que en los atributos pueden o no llevar tipo de dato.

En la sección de Structs se detallará más al respecto de estos.

Expresiones

JOLC acepta operaciones aritmeticas, relacionales y logicas de la siguiente forma:

Aritméticas

Entre las operaciones aritmeticas disponibles vamos a encontrar las siguientes:

  • Suma: La suma de dos expresiones se define por el símbolo +
  • Resta: La resta de dos expresiones y la negación de una expresión aritmetica se define por el símbolo -
  • Multiplicación: La multiplicación de dos expresiones se define por el símbolo *
  • División: La división de dos expresiones se define por el símbolo /
  • Modulo: El modulo entre dos expresiones se define por el símbolo %
  • Potencia: La potenciación de una expresión se define por el símbolo ^
  • Nativas: JOLC posee 6 funciones nativas para la resolución de expresiones, entre ellas se encuentran:
    • log10: Resuelve el logaritmo de base 10 del numero que se ingrese
    • log: Recibe como parametro la base y el numero del cual se desea obtener el logaritmo con la base especificada. Ejemplo: log(2,4)
    • sin: Resuelve la función seno del número que se ingrese
    • cos: Resuelve la función coseno del numero que se ingrese
    • tan: Resuelve la función tangente del numero que se ingrese
    • sqrt: Resuelve la raiz cuadrada del numero que se ingrese
    #Se expresa de la siguiente manera:
    sin(134)
    log10(100)
    cos(var1)
    tan(12)
    sqrt(16)

Relacionales

Entre las operaciones relacionales disponibles vamos a encontrar las siguientes:

  • Igualdad: Esta se define por el símbolo ==
  • Diferenciación: Esta se define por el símbolo !=
  • Mayor que: Esta se define por el símbolo >
  • Menor que: Esta se define por el símbolo <
  • Mayor o igual que: Esta se define por el símbolo >=
  • Menor o igual que: Esta se define por el símbolo <=

Lógicas

Entre las operaciones lógicas disponibles vamos a encontrar las siguientes:

  • AND: Esta se define por el símbolo &&
  • OR: Esta se define por el símbolo ||
  • NOT: Esta se define por el símbolo !

Cadenas

Entre las operaciones con cadenas (strings) vamos a encontrar las siguientes:

  • Concatenación: La unión de dos cadenas de texto se define por el símbolo *
    "para" * "caidismo" = "paracaidismo"
  • Repetición: Permite que una cadena de texto se repita cierto número de veces, esta se define por el símbolo ^
    "Cadena"^3 = "CadenaCadenaCadena"
  • Acceso a una pocisión: El acceso a un elemento de una cadena se define de la siguiente manera: string[posición], el cual devolvera el caracter correspondiente a esa posición
    animal = "Tigre";
    println(animal[2]); #i
  • Acceso a una porción: El acceso a una porción de una cadena se define de la siguiente manera: string[inicial:final], el cual devolvera la cadena correspondiente al intervalo definido.
    animal = "Tigre";
    println(animal[2:4]); #igr
  • Tamaño de una cadena: La obtención del número de elementos de una cadena se define por la función length(cadena)
    animal = "Tigre";
    println(length(animal)); #5
  • Cadena en mayusculas: Una cadena puede ser convertida a mayusculas con la utilización de la función uppercase(cadena)
    animal = "Tigre";
    println(uppercase(animal)); #TIGRE
  • Cadena en minusculas: Una cadena puede ser convertida a mayusculas con la utilización de la función lowercase(cadena)
    animal = "Tigre";
    println(lowercase(animal)); #tigre

Operador ternario

El operador ternario es utilizado cuando se necesita entre diferentes expresiones a travez de una condición

(EXPRESIÓN RELACIONAL O LOGICA) ? RESULTADO SI ES VERDADERO : RESULTADO SI ES FALSO

Ejemplo:

respuesta = edad >= 50 ? "Puede vacunarse" : "No puede vacunarse";

println(animal == "Perro" ? 15 : 10);

Instrucciones

JOLC contará con varias instrucciones para su ejecución, cada instrucción debe terminar con un punto y coma (;). Las instrucciones que JOLC acepta son:

Impresión

JOLC cuenta con 2 distintas instrucciones de imprimir.

print(expresión);        # Esta imprime sin realizar un salto de línea
println(expresión);      # Esta imprime realizando un salto de línea

Para imprimir más de un valor por línea, se puede imprimir una secuencia de valores separados por comas. También dentro de las cadenas se pueden colocar cualquier expresión utilizando el operador $. Por ejemplo:

println("+", "-");       # Imprime + -
print("El resultado de 2 + 2 es $(2 + 2)");  # Imprime El resultado de 2 + 2 es 4
println("$a $(b[1])"); # Imprime el valor de a y el valor de b[1]

JOLC también tiene la opción de imprimir arreglos y struct. Por ejemplo:

    a = [0, 1, 2];
    println(a);          # Imprime [0, 1, 2]
    s = Hora(10, 30);
    print(s);            # Imprime Hora(10, 30)

Declaraciones y Asignaciones

JOLC permite la declaración y asignación de variables, las variables pueden cambiar su tipo de dato en cualquier momento

  • Declaración: JOLC permite declarar variables de dos maneras:
    ID = Expresión ::TIPO;
    ó
    ID = Expresión;

Ejemplo:

    x = (3*5)::Int64;
    y = (10/4)::Float64;
    str = "Saludo"::String;
    var1 = true;

Nótese que la expresión ::TIPO es opcional.

  • Asignación: JOLC permite asignar valores a variables existentes de la siguiente manera:
    ID = Expresión;

Ejemplo:

    var1 = "Adios";
    v = 89 - 9;
  • global y local: JOLC permite definir el uso de variables globales o locales a travez de las palabras reservadas global y local, esto quiere decir que, si una variable es declara en el entorno global y se le quiere asignar un nuevo valor dentro de una función se debe de utilizar la palabra global:
    x = 8200::Int64;
    
    function suma(a,b)
      global x = a + b;
    end;
    Si dentro de un ciclo se busca crear una nueva variable con un id igual a una variable en un entorno externo se usa la palabra local:
      x = 15::Int64;
    
      function numero()
    
          local x = 80; #local de la funcion
          y = 0;
          while (y < 10)
              local x = 9; #local del ciclo
              y = y + 1;
              println(x) #9
          end;
          println(x) #80
      end;
      numero();
      println(x) #15

Llamada a funciones

Una llamada a función es como un desvío en el flujo de la ejecución. En lugar de pasar a la siguiente sentencia, el flujo salta al cuerpo de la función, ejecuta esta y regresa para continuar después de la llamada a la función.

Para llamar a una función se realiza de la siguiente manera:

NOMBRE_FUNCION(LISTA_PARAMETROS);

Ejemplo:

ordenamiento(arr1,arr2);
imprimirLista(lista);
nuevaLinea();

Si la función cuenta con más de un parámetro estos se separan por medio de ,. Además es importante tener en cuenta que cuando se pasa un arreglo o struct como argumento de una función, en realidad se pasa una referencia de este. Por lo que cualquier cambio que se realice al parámetro, se podrá observar después de salir de la función.

Las llamadas a funciones también se pueden utilizar en expresiones, debido a que existen funciones que retornan un valor.

Distintas Funciones Nativas

JOLC utiliza diversas funciones nativas para sus expresiones, estas son:

  • Parse: Toma una cadena y la convierte al tipo de numero que se le indice si es posible.
    parse(Int64,"8200")
    ó
    parse(Float64,"3.13159")
  • Trunc: Convierte un número flotante a un número entero sin redondearlo
    trunc(Int64, 3.99999)  # retorna 3
  • Float: Convierte un número entero a un número flotante
    float(34)  # retorna 34.0
  • String: Convierte el argumento en una cadena, puede usarse en numeros y en arreglos
    string(45.87)  # retorna "45.87"
    string([1,2,3])  # retorna "[1,2,3]"
  • typeof: Muestra el tipo del argumento
    typeof(5 * 5) #Int64

Funciones

Las funcioens son secuencias de sentencias que ejecuta una operación que nosotros deseamos. Cuando se crea una función se especifica su nombre y secuencia de sentencias. Luego, ya se puede llamar a estas usando su nombre y los parámetros solicitados. Se definen las funciones en JOLC así:

function NOMBRE_FUNCION(LISTA_PARAMETROS)
    LISTA_INSTRUCCIONES
end;

Las instrucciones se separarán utilizando ;. Por ejemplo:

function imprimirHola()
    println("Hola");
    println("Hola");
end;

Además, los parámetros de las funciones vendrán separadas por , y podrán o no llevar tipo de dato.

function sumar(num1::Int64, num2)
    return num1 + num2;
end;

Hay que tomar en cuenta que las variables y parámetros que se creen dentro de una función son locales, es decir que únicamente existen dentro de la función.

Las funciones también pueden llamarse a sí mismas. Lo que permite una gran variedad de aplicaciones en estructuras de datos y algoritmos de ordenamiento.

Condicionales

JOLC cuenta con sentencias condicionales, lo que permite que un bloque de codigo pueda ser o no ejecutado. Estas se definen por if,if...else y if...elseif. Su estructura es la siguiente:

if CONDICION
    LISTA_INTRUCCIONES
end;

if CONDICION1
    LISTA_INTRUCCIONES
elseif CONDICION2
    LISTA_INTRUCCIONES
else
    LISTA_INTRUCCIONES
end;

Ejemplo:

if x == 8
    var1 = (x + 8)::Int64;
    println(sqrt(var1));
end;

if x == 8
    var1 = (x + 8)::Int64;
    println(sqrt(var1));
elseif x < 8
    var1 = (x/3)::Float64;
    println(sin(var1));
else
    println("Error");
end;

Loops

JOLC cuenta con sentencias iterativas, lo que permite ejecutar repetidamente un bloque de sentencias. Existen 2 de estas, el ciclo while y el ciclo for.

While

La sentencia while sigue la siguiente estructura:

while CONDICION
    LISTA_INSTRUCCIONES
end;

Ejemplo:

while var1 < 10
    println(var1);
    var1 = var1 + 1;
end;

Y se ejecutará hasta que la condición del while se vuelva false. De manera más formal, el flujo de un while es el siguiente:

  1. Se determina si la condición es true o false.
  2. Si es false, se sale de la sentencia while y continúa la ejecución con la siguiente sentencia.
  3. Si es true, ejecuta cada una de las sentencias en la lista de instrucciones.

For

La sentencia for en JOLC puede iterar sobre tipos que son iterables. Como lo son rangos, Array, String.

Sigue la siguiente estructura:

for ID in (RANGO | STRING | ARRAY)
    LISTA_INSTRUCCIONES
end;

Algunos ejemplos de for en JOLC son:

for i in 1:4                # Recorre rango de 1:4
    print(i, " ");          # Únicamente se recorre ascendentemente
end;                        # Imprime 1 2 3 4

for letra in "Hola Mundo!"  # Recorre las letras de la cadena
    print(letra, "-");      # Imprime H-o-l-a-M-u-n-d-o-!
end;

cadena = "OLC2";
for letra in cadena
    print(letra, "-");      # Imprime O-L-C-2
end;

for animal in ["perro", "gato", "tortuga"]
    println("$animal es mi favorito");
    #= Imprime
        perro es mi favorito
        gato es mi favorito
        tortuga es mi favorito
    =#
end;

arr = [1,2,3,4,5]
for numero in arr[2:4]
    print(numero, " ")      # Imprime 2 3 4
end;

Hay que tomar en cuenta en los arreglos que también puede ser un rango de algún arreglo. Por ejemplo:

for it in a[begin:end]
    # Haz algo
end;

Dentro de los ciclos también existen las sentencias de control break y continue. Las cuales, una termina el bucle y la otra regresa al inicio del bucle ignorando las sentencias faltantes.

Arreglos

Como se a mencionado JOLC cuenta con arreglos, los cuales pueden ser definidos mediante una sintaxis. Los valores de los arreglos pueden ser de cualquier tipo.

[8,true,"JOLC",[1,2,3]]

Para acceder a una posición en específico del arreglo, se debe definir una expresión que de como resultado un numero entero dentro de corchetes. los indices en JOLC inician desde el numero 1 en adelante.

arr = ["H","O","L","A"];
print(arr[1]) #H

JOLC tambien permite que se acceda a una porción de un arreglo, esto se define mediante la sintaxis begin:end, el cual debe ir dentro de corchetes y devolvera un arreglo con los limites establecidos. Se debe tomar en cuenta que las palabras begin y end pueden ser utilizadas para indicar el inicio y el final del arreglo respectivamente

arr = [1,2,3,4,5,6];
print(arr[2:4]); #[2,3,4]

print(arr[begin:4]) #[1,2,3,4]
print(arr[4:end]) #[4,5,6]

Copiar un arreglo:

JOLC permite crear una copia de un arreglo utilizando el símbolo :, como los arreglos son mutables, es útil hacer una copia antes de realizar operaciones que las modifiquen.

arr = [1,2,3,4,5,6];
arr2 = arr[:];

arr[2] = 0;

print(arr) #[1,0,3,4,5,6]
print(arr2) #[1,2,3,4,5,6]

Funciones nativas con arreglos:

JOLC cuenta con 2 funciones nativas con arreglos, en los que podemos encontrar:

  • Push: inserta un nuevo valor al final del arreglo, se define como:
push!(nombre_arreglo,expresión);

Ejemplo:

arr = [1,2,3,4,5,6];
push!(arr,7); # arr = [1,2,3,4,5,6,7]
  • Pop: elimina y devuelve el ultimo valor de un arreglo, se define como:
pop!(nombre_arreglo,expresión);

Ejemplo:

arr = [1,2,3,4,5,6];
pop!(arr); # retorna 6, arr = [1,2,3,4,5]

Length: La obtención del tamaño de un arreglo, se define como:

length(arreglo)

Ejemplo:

arr = [1,2,3,4,5,6];
length(arr); # 6

Operador punto con arreglos:

JOLC permite la utilización del operador punto (.) para realizar diferentes operaciones aritmeticas, trigonometricas, relaciones o cualquier otro tipo de función sobre cada valor en un arreglo.

arr = [1,2,3];
print(arr.*2) #[2,4,6]

arr2 = sin.(arr) #[0.8415, 0.9093, 0.1411]

Structs

Como se menciono en secciones anteriores, JOLC cuenta con tipos compuestos que los desarrolladores podrán definir mediante una sintaxis. Existen de tipo mutables e inmutables, con una diferencia bastante importante. Para la declaración de estos se utiliza la siguiente sintaxis:

# Struct inmutable
struct NOMBRE_STRUCT
    LISTA_ATRIBUTOS
end;

# Struct mutable
mutable struct NOMBRE_STRUCT
    LISTA_ATRIBUTOS
end;

Y para la creación de variables con nuestro Struct, ya sea mutable e inmutable:

ID = NOMBRE_STRUCT(LISTA_VALORES);

Siendo los valores los correspondientes a sus atributos en la lista de atributos.

Los atributos de los Struct pueden ser utilizados como parte de cualquier expresión. Para acceder a los atributos de los Struct, se utiliza la notación ..

ID.ID

También si nosotros deseamos modificar únicamente uno de los atributos de nuestro Struct, ahí es donde entra la importancia de los dos tipos de Struct en JOLC. Los Struct que son inmutables no aceptan instrucciones de asignación en sus atributos, no se les puede cambiar el valor. En cambio, los Struct mutables si aceptan este tipo de instrucciones.

# Suponiendo que X es una variable Struct inmutable
X.atributo = expresión
ERROR !!! No se puede cambiar Struct inmutable

# Suponiendo que Y es una variable Struct mutable
Y.atributo = expresión

Otros aspectos importantes de los Structs es que estos pueden ser llamados como parámetros en las funciones y, al igual que los arreglos, se pasan por referencia. Por lo que el valor de los atributos de los Structs también cambia. Por ejemplo:

mutable struct Estructura
    x;
end;

function cambiarAtributo(s)
    s.x = 10;
end;

a = Estructura(0);
println(a);             # Imprime 'Estructura(0)'
println(a.x);           # Imprime 0

cambiarAtributo(a);
println(a);             # Imprime 'Estructura(10)'
println(a.x);           # Imprime 10

Hay que tomar en cuenta de que si la estructura fuera de tipo inmutable, esta mostraría un error por la asignación.

Se debe de tomar en cuenta que los Struct se pueden utilizar como retorno de una función.