Translate

sábado, 21 de enero de 2023

Pattern matching: las expresiones is y switch, y los operadores and, or y not en C# parte 5


Patron var 

Utiliza un patrón var para hacer coincidir cualquier expresión, incluido nulo, y asigna su resultado a una nueva variable local, como muestra el siguiente ejemplo:


static bool IsAcceptable(int id, int absLimit) =>

    SimulateDataFetch(id) is var results 

    && results.Min() >= -absLimit 

    && results.Max() <= absLimit;


static int[] SimulateDataFetch(int id)

{

    var rand = new Random();

    return Enumerable

               .Range(start: 0, count: 5)

               .Select(s => rand.Next(minValue: -10, maxValue: 11))

               .ToArray();

}


Un patrón var es útil cuando necesitamos una variable temporal dentro de una expresión booleana para contener el resultado de cálculos intermedios. También podemos usar un patrón var cuando necesitamos realizar más comprobaciones cuando las mayúsculas y minúsculas protegen una expresión o declaración de cambio, como muestra el siguiente ejemplo:

public record Point(int X, int Y);

static Point Transform(Point point) => point switch

{

    var (x, y) when x < y => new Point(-x, y),

    var (x, y) when x > y => new Point(x, -y),

    var (x, y) => new Point(x, y),

};


static void TestTransform()

{

    Console.WriteLine(Transform(new Point(1, 2)));  // output: Point { X = -1, Y = 2 }

    Console.WriteLine(Transform(new Point(5, 2)));  // output: Point { X = 5, Y = -2 }

}


En el ejemplo anterior, el patrón var (x, y) es equivalente a un patrón posicional (var x, var y).

En un patrón var, el tipo de una variable declarada es el tipo de tiempo de compilación de la expresión que se compara con el patrón.


Patrón descartar 

Utiliza un patrón de descarte _ para hacer coincidir cualquier expresión, incluido nulo, como muestra el siguiente ejemplo:

Console.WriteLine(GetDiscountInPercent(DayOfWeek.Friday));  // output: 5.0

Console.WriteLine(GetDiscountInPercent(null));  // output: 0.0

Console.WriteLine(GetDiscountInPercent((DayOfWeek)10));  // output: 0.0


static decimal GetDiscountInPercent(DayOfWeek? dayOfWeek) => dayOfWeek switch

{

    DayOfWeek.Monday => 0.5m,

    DayOfWeek.Tuesday => 12.5m,

    DayOfWeek.Wednesday => 7.5m,

    DayOfWeek.Thursday => 12.5m,

    DayOfWeek.Friday => 5.0m,

    DayOfWeek.Saturday => 2.5m,

    DayOfWeek.Sunday => 2.0m,

    _ => 0.0m,

};


En el ejemplo anterior, se usa un patrón de descarte para controlar valores nulos y enteros que no tienen el miembro correspondiente de la enumeración DayOfWeek. Eso garantiza que una expresión de cambio en el ejemplo maneje todos los valores de entrada posibles. Si no usa un patrón de descarte en una expresión de cambio y ninguno de los patrones de la expresión coincide con una entrada, el tiempo de ejecución genera una excepción. El compilador genera una advertencia si una expresión de cambio no maneja todos los valores de entrada posibles.

Un patrón de descarte no puede ser un patrón en una expresión is o una declaración de cambio. En esos casos, para hacer coincidir cualquier expresión, podemos usar un patrón var con un descarte: var _.


Patrón entre paréntesis

A partir de C# 9.0, podemos poner paréntesis alrededor de cualquier patrón. Por lo general, hace eso para enfatizar o cambiar la precedencia en patrones lógicos, como muestra el siguiente ejemplo:

if (input is not (float or double))

{

    return;

}

Patrones de lista

A partir de C# 11, puede hacer coincidir una matriz o una lista con una secuencia de patrones, como muestra el siguiente ejemplo:

int[] numbers = { 1, 2, 3 };


Console.WriteLine(numbers is [1, 2, 3]);  // True

Console.WriteLine(numbers is [1, 2, 4]);  // False

Console.WriteLine(numbers is [1, 2, 3, 4]);  // False

Console.WriteLine(numbers is [0 or 1, <= 2, >= 3]);  // True

Como muestra el ejemplo anterior, un patrón de lista coincide cuando cada patrón anidado coincide con el elemento correspondiente de una secuencia de entrada. Puede usar cualquier patrón dentro de un patrón de lista. Para hacer coincidir cualquier elemento, use el patrón de descarte o, si también desea capturar el elemento, el patrón var, como muestra el siguiente ejemplo:

List<int> numbers = new() { 1, 2, 3 };

if (numbers is [var first, _, _])

{

    Console.WriteLine($"The first element of a three-item list is {first}.");

}

// Output:

// The first element of a three-item list is 1.

Los ejemplos anteriores comparan una secuencia de entrada completa con un patrón de lista. Para hacer coincidir los elementos solo al principio o al final de una secuencia de entrada, podemos usar el patrón de división .. dentro de un patrón de lista, como muestra el siguiente ejemplo:

Console.WriteLine(new[] { 1, 2, 3, 4, 5 } is [> 0, > 0, ..]);  // True

Console.WriteLine(new[] { 1, 1 } is [_, _, ..]);  // True

Console.WriteLine(new[] { 0, 1, 2, 3, 4 } is [> 0, > 0, ..]);  // False

Console.WriteLine(new[] { 1 } is [1, 2, ..]);  // False


Console.WriteLine(new[] { 1, 2, 3, 4 } is [.., > 0, > 0]);  // True

Console.WriteLine(new[] { 2, 4 } is [.., > 0, 2, 4]);  // False

Console.WriteLine(new[] { 2, 4 } is [.., 2, 4]);  // True


Console.WriteLine(new[] { 1, 2, 3, 4 } is [>= 0, .., 2 or 4]);  // True

Console.WriteLine(new[] { 1, 0, 0, 1 } is [1, 0, .., 0, 1]);  // True

Console.WriteLine(new[] { 1, 0, 1 } is [1, 0, .., 0, 1]);  // False


Un patrón de división coincide con cero o más elementos. Puede usar como máximo un patrón de división en un patrón de lista.

También puede anidar un subpatrón dentro de un patrón de división, como muestra el siguiente ejemplo:

void MatchMessage(string message)

{

    var result = message is ['a' or 'A', .. var s, 'a' or 'A']

        ? $"Message {message} matches; inner part is {s}."

        : $"Message {message} doesn't match.";

    Console.WriteLine(result);

}


MatchMessage("aBBA");  // output: Message aBBA matches; inner part is BB.

MatchMessage("apron");  // output: Message apron doesn't match.


void Validate(int[] numbers)

{

    var result = numbers is [< 0, .. { Length: 2 or 4 }, > 0] ? "valid" : "not valid";

    Console.WriteLine(result);

}


Validate(new[] { -1, 0, 1 });  // output: not valid

Validate(new[] { -1, 0, 0, 1 });  // output: valid


Probando Fedora

Sigo probando distros de linux y ahora le toca el gran Fedora Linux. Que yo usaba en mi antigua pc personal y que andaba hermoso. Ahora instale la versión Gnome, no sé si no me pregunto si queria kde o no lo vi, en el proceso de instalación. 

Me cuesta mucho opinar porque es casi un gnome sin modificaciones. No esta nada personalizado, personalmente me gustan las distros que tienen un estilo propio, en este caso a simple vista no se ven cambios: Por supuesto trae todas las herramientas de administración que son super utiles pero en lo visual no suma mucho como opción de escritorio. 

Les dejo unos screenshots :

 






Dejo link: https://getfedora.org/es/

miércoles, 18 de enero de 2023

Pattern matching: las expresiones is y switch, y los operadores and, or y not en C# parte 4


Patrón posicional

Utiliza un patrón posicional para deconstruir un resultado de expresión y hacer coincidir los valores resultantes con los patrones anidados correspondientes, como muestra el siguiente ejemplo:

public readonly struct Point

{

    public int X { get; }

    public int Y { get; }


    public Point(int x, int y) => (X, Y) = (x, y);


    public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);

}


static string Classify(Point point) => point switch

{

    (0, 0) => "Origin",

    (1, 0) => "positive X basis end",

    (0, 1) => "positive Y basis end",

    _ => "Just a point",

};

En el ejemplo anterior, el tipo de una expresión contiene el método Deconstruct, que se utiliza para deconstruir el resultado de una expresión. También puede hacer coincidir expresiones de tipos de tupla con patrones posicionales. De esa manera, puede hacer coincidir varias entradas con varios patrones, como muestra el siguiente ejemplo:

static decimal GetGroupTicketPriceDiscount(int groupSize, DateTime visitDate)

    => (groupSize, visitDate.DayOfWeek) switch

    {

        (<= 0, _) => throw new ArgumentException("Group size must be positive."),

        (_, DayOfWeek.Saturday or DayOfWeek.Sunday) => 0.0m,

        (>= 5 and < 10, DayOfWeek.Monday) => 20.0m,

        (>= 10, DayOfWeek.Monday) => 30.0m,

        (>= 5 and < 10, _) => 12.0m,

        (>= 10, _) => 15.0m,

        _ => 0.0m,

    };

El ejemplo anterior usa patrones relacionales y lógicos, que están disponibles en C# 9.0 y versiones posteriores.

Se puede usar los nombres de los elementos de tupla y los parámetros de Deconstrucción en un patrón posicional, como muestra el siguiente ejemplo:

var numbers = new List<int> { 1, 2, 3 };

if (SumAndCount(numbers) is (Sum: var sum, Count: > 0))

{

    Console.WriteLine($"Sum of [{string.Join(" ", numbers)}] is {sum}");  // output: Sum of [1 2 3] is 6

}


static (double Sum, int Count) SumAndCount(IEnumerable<int> numbers)

{

    int sum = 0;

    int count = 0;

    foreach (int number in numbers)

    {

        sum += number;

        count++;

    }

    return (sum, count);

}


También puede extender un patrón posicional de cualquiera de las siguientes maneras:

  • Agregue una verificación de tipo en tiempo de ejecución y una declaración de variable, como muestra el siguiente ejemplo:

public record Point2D(int X, int Y);

public record Point3D(int X, int Y, int Z);


static string PrintIfAllCoordinatesArePositive(object point) => point switch

{

    Point2D (> 0, > 0) p => p.ToString(),

    Point3D (> 0, > 0, > 0) p => p.ToString(),

    _ => string.Empty,

};

El ejemplo anterior usa registros posicionales que proporcionan implícitamente el método Deconstruct.

  • Se puede utilizar un patrón de propiedad dentro de un patrón posicional, como muestra el siguiente ejemplo:


public record WeightedPoint(int X, int Y)

{

    public double Weight { get; set; }

}


static bool IsInDomain(WeightedPoint point) => point is (>= 0, >= 0) { Weight: >= 0.0 };


  • Y Tambien se puede combinar los dos usos anteriores, como muestra el siguiente ejemplo:


if (input is WeightedPoint (> 0, > 0) { Weight: > 0.0 } p)

{

    // ..

}


Un patrón posicional es un patrón recursivo. Es decir, puede utilizar cualquier patrón como patrón anidado.


Conoce 3 etapas para aumentar la innovación durante los cambios

 

Quiero compartir un ebook de la gente de oracle : 

lunes, 16 de enero de 2023

Pattern matching: las expresiones is y switch, y los operadores and, or y not en C# parte 3


Patrones lógicos

A partir de C# 9.0, utiliza los combinadores de patrones not, and y or para crear los siguientes patrones lógicos:

  • Negación que coincide con una expresión cuando el patrón negado no coincide con la expresión. El siguiente ejemplo muestra cómo puede negar un patrón nulo constante para verificar si una expresión no es nula:

if (input is not null)

{

    // ...

}

 

  • Conjuntiva (and) que coincide con una expresión cuando ambos patrones coinciden con la expresión. El siguiente ejemplo muestra cómo puede combinar patrones relacionales para verificar si un valor está en un cierto rango:

Console.WriteLine(Classify(13));  // output: High
Console.WriteLine(Classify(-100));  // output: Too low
Console.WriteLine(Classify(5.7));  // output: Acceptable

static string Classify(double measurement) => measurement switch
{
    < -40.0 => "Too low",
    >= -40.0 and < 0 => "Low",
    >= 0 and < 10.0 => "Acceptable",
    >= 10.0 and < 20.0 => "High",
    >= 20.0 => "Too high",
    double.NaN => "Unknown",
};

  • Disyuntiva (or) que coincide con una expresión cuando cualquiera de los patrones coincide con la expresión, como muestra el siguiente ejemplo:

Console.WriteLine(GetCalendarSeason(new DateTime(2021, 1, 19)));  // output: winter

Console.WriteLine(GetCalendarSeason(new DateTime(2021, 10, 9)));  // output: autumn

Console.WriteLine(GetCalendarSeason(new DateTime(2021, 5, 11)));  // output: spring


static string GetCalendarSeason(DateTime date) => date.Month switch

{

    3 or 4 or 5 => "spring",

    6 or 7 or 8 => "summer",

    9 or 10 or 11 => "autumn",

    12 or 1 or 2 => "winter",

    _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),

};

Como muestra el ejemplo anterior, puede utilizar repetidamente los combinadores de patrones en un patrón.


Precedencia y orden de verificación

La siguiente lista ordena los combinadores de patrones comenzando desde la precedencia más alta hasta la más baja:

  • not
  • and
  • or

Para especificar explícitamente la precedencia, podemos usar paréntesis, como muestra el siguiente ejemplo:

static bool IsLetter(char c) => c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z');


Patrón de propiedad

Se utiliza un patrón de propiedad para hacer coincidir las propiedades o campos de una expresión con patrones anidados, como muestra el siguiente ejemplo:

static bool IsConferenceDay(DateTime date) => date is { Year: 2020, Month: 5, Day: 19 or 20 or 21 };

Un patrón de propiedad coincide con una expresión cuando el resultado de una expresión no es nulo y cada patrón anidado coincide con la propiedad o el campo correspondiente del resultado de la expresión.

También puede agregar una verificación de tipo en tiempo de ejecución y una declaración de variable a un patrón de propiedad, como muestra el siguiente ejemplo:


Console.WriteLine(TakeFive("Hello, world!"));  // output: Hello

Console.WriteLine(TakeFive("Hi!"));  // output: Hi!

Console.WriteLine(TakeFive(new[] { '1', '2', '3', '4', '5', '6', '7' }));  // output: 12345

Console.WriteLine(TakeFive(new[] { 'a', 'b', 'c' }));  // output: abc


static string TakeFive(object input) => input switch

{

    string { Length: >= 5 } s => s.Substring(0, 5),

    string s => s,


    ICollection<char> { Count: >= 5 } symbols => new string(symbols.Take(5).ToArray()),

    ICollection<char> symbols => new string(symbols.ToArray()),


    null => throw new ArgumentNullException(nameof(input)),

    _ => throw new ArgumentException("Not supported input type."),

};

Un patrón de propiedad es un patrón recursivo. Es decir, puede utilizar cualquier patrón como patrón anidado. Se puede utilizar un patrón de propiedad para hacer coincidir partes de datos con patrones anidados, como muestra el siguiente ejemplo:

public record Point(int X, int Y);

public record Segment(Point Start, Point End);


static bool IsAnyEndOnXAxis(Segment segment) =>

    segment is { Start: { Y: 0 } } or { End: { Y: 0 } };


El ejemplo anterior usa dos funciones disponibles en C# 9.0 y versiones posteriores: o combinador de patrones y tipos de registro.

A partir de C# 10, puede hacer referencia a propiedades o campos anidados dentro de un patrón de propiedad. Esta capacidad se conoce como patrón de propiedad extendida. Por ejemplo, puede refactorizar el método del ejemplo anterior en el siguiente código equivalente:


static bool IsAnyEndOnXAxis(Segment segment) =>

    segment is { Start.Y: 0 } or { End.Y: 0 };



sábado, 14 de enero de 2023

Probando OpenSuse

Sigo probando distros de linux y ahora le toca el gran OpenSuse. Que yo usaba en mi antigua pc personal y que andaba hermoso. Pero ahora lo estoy probando y me desilusiono un poquito.  

Lo veo muy similar al que usaba, como que se quedo un poco en el tiempo o capaz que soy yo que lo esperaba más evolucionado y no esta el menú que lo distinguia. 

Pero salvo esos detalles, no deja de estar muy bueno, les dejo unos screenshots : 






Dejo link : https://www.opensuse.org/


viernes, 13 de enero de 2023

Pattern matching: las expresiones is y switch, y los operadores and, or y not en C# parte 2


Patrón constante

Utiliza un patrón constante para probar si el resultado de una expresión es igual a una constante especificada, como muestra el siguiente ejemplo:


public static decimal GetGroupTicketPrice(int visitorCount) => visitorCount switch

{

    1 => 12.0m,

    2 => 20.0m,

    3 => 27.0m,

    4 => 32.0m,

    0 => 0.0m,

    _ => throw new ArgumentException($"Not supported number of visitors: {visitorCount}", nameof(visitorCount)),

};


En un patrón constante, se puede usar cualquier expresión constante, como:

  • un literal numérico entero o de coma flotante
  • un char
  • un literal de cadena.
  • un valor booleano verdadero o falso
  • un valor de enumeración
  • el nombre de un campo const declarado o local
  • nulo

La expresión debe ser un tipo que se pueda convertir al tipo constante, con una excepción: una expresión cuyo tipo sea Span<char> o ReadOnlySpan<char> se puede comparar con cadenas constantes en C# 11 y versiones posteriores.

Se puede utilizar un patrón constante para verificar si hay valores nulos, como muestra el siguiente ejemplo:


if (input is null)

{

    return;

}


El compilador garantiza que no se invoca ningún operador de igualdad sobrecargado por el usuario == cuando se evalúa la expresión x es nula.

A partir de C# 9.0, puede usar un patrón de constante nulo negado para verificar si no es nulo, como muestra el siguiente ejemplo:


if (input is not null)

{

    // ...

}


Patrones relacionales

A partir de C# 9.0, utiliza un patrón relacional para comparar el resultado de una expresión con una constante, como muestra el siguiente ejemplo:


Console.WriteLine(Classify(13));  // output: Too high

Console.WriteLine(Classify(double.NaN));  // output: Unknown

Console.WriteLine(Classify(2.4));  // output: Acceptable


static string Classify(double measurement) => measurement switch

{

    < -4.0 => "Too low",

    > 10.0 => "Too high",

    double.NaN => "Unknown",

    _ => "Acceptable",

};

En un patrón relacional, puede utilizar cualquiera de los operadores relacionales <, >, <= o >=. La parte derecha de un patrón relacional debe ser una expresión constante. La expresión constante puede ser de tipo entero, punto flotante, carácter o enumeración.

Para verificar si el resultado de una expresión está en un cierto rango, compárelo con una conjuntiva y un patrón, como muestra el siguiente ejemplo:


Console.WriteLine(GetCalendarSeason(new DateTime(2021, 3, 14)));  // output: spring

Console.WriteLine(GetCalendarSeason(new DateTime(2021, 7, 19)));  // output: summer

Console.WriteLine(GetCalendarSeason(new DateTime(2021, 2, 17)));  // output: winter


static string GetCalendarSeason(DateTime date) => date.Month switch

{

    >= 3 and < 6 => "spring",

    >= 6 and < 9 => "summer",

    >= 9 and < 12 => "autumn",

    12 or (>= 1 and < 3) => "winter",

    _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),

};


Si el resultado de una expresión es nulo o no se convierte al tipo de una constante mediante una conversión anulable o unboxing, un patrón relacional no coincide con una expresión.



jueves, 12 de enero de 2023

[eBook] Security as Code

 

EBOOK

[eBook] Security as Code

Hi Emanuel,

To build secure and resilient applications and keep pace with customer demand, your entire app-delivery team – developers, DevOps, and security engineering – must work together and move towards a comprehensive DevSecOps strategy that ensures consistent app security. In this eBook, authors BK Sarthak Das and Virginia Chu show you how to implement such a strategy. In Security as Code, you'll learn how to create a secure containerized application with Kubernetes using CI/CD tooling from AWS and open source providers.

In this eBook you will learn:

  • About enabling consistent app security by creating templates with declarative code to automate security and keep developers agile
  • How to set up infrastructure as code and run scans to detect misconfigured resources in your code
  • The top four high-level roles a DevSecOps team should have
  • How to secure your AWS environment and Amazon EKS cluster, with step-by-step exercises on implementing security as code within the CI/CD pipeline

miércoles, 11 de enero de 2023

Pattern matching: las expresiones is y switch, y los operadores and, or y not en C#


Las siguientes expresiones e instrucciones de C# admiten pattern matching:

  • la expresión is 
  • la sentencia switch 
  • y la expresión switch 

En esas construcciones, se puede hacer coincidir una expresión de entrada con cualquiera de los siguientes patrones:

  • Patrón de declaración: para verificar el tipo de tiempo de ejecución de una expresión y, si una coincidencia tiene éxito, asignar un resultado de expresión a una variable declarada.
  • Patrón de tipo: para comprobar el tipo de tiempo de ejecución de una expresión. 
  • Patrón constante: para probar si el resultado de una expresión es igual a una constante especificada.
  • Patrones relacionales: para comparar el resultado de una expresión con una constante especificada. 
  • Patrones lógicos: para probar si una expresión coincide con una combinación lógica de patrones. 
  • Patrón de propiedad: para probar si las propiedades o campos de una expresión coinciden con patrones anidados.
  • Patrón posicional: para deconstruir un resultado de expresión y probar si los valores resultantes coinciden con patrones anidados.
  • patrón var: para hacer coincidir cualquier expresión y asignar su resultado a una variable declarada.
  • Patrón de descarte: para que coincida con cualquier expresión.
  • Patrones de lista: para probar si los elementos de secuencia coinciden con los patrones anidados correspondientes. 
Los patrones lógicos, de propiedad, posicionales y de lista son patrones recursivos. Es decir, pueden contener patrones anidados.

Patrones de tipo y declaración

Se utiliza patrones de declaración y tipo para verificar si el tipo de tiempo de ejecución de una expresión es compatible con un tipo dado. Con un patrón de declaración, también se puede declarar una nueva variable local. Cuando un patrón de declaración coincide con una expresión, a esa variable se le asigna un resultado de expresión convertida, como muestra el siguiente ejemplo:

object greeting = "Hello, World!";
if (greeting is string message)
{
    Console.WriteLine(message.ToLower());  // output: hello, world!
}

Un patrón de declaración con tipo T coincide con una expresión cuando el resultado de una expresión no es nulo y cualquiera de las siguientes condiciones es verdadera:

  • El tipo de tiempo de ejecución de un resultado de expresión es T.
  • El tipo de tiempo de ejecución de un resultado de expresión se deriva del tipo T, implementa la interfaz T o existe otra conversión de referencia implícita a T. El siguiente ejemplo muestra dos casos en los que esta condición sean verdadera:

var numbers = new int[] { 10, 20, 30 };
Console.WriteLine(GetSourceLabel(numbers));  // output: 1

var letters = new List<char> { 'a', 'b', 'c', 'd' };
Console.WriteLine(GetSourceLabel(letters));  // output: 2

static int GetSourceLabel<T>(IEnumerable<T> source) => source switch
{
    Array array => 1,
    ICollection<T> collection => 2,
    _ => 3,
};

En el ejemplo anterior, en la primera llamada al método GetSourceLabel, el primer patrón coincide con un valor de argumento porque el tipo de tiempo de ejecución del argumento int[] se deriva del tipo Array. En la segunda llamada al método GetSourceLabel, el tipo List<T> en tiempo de ejecución del argumento no se deriva del tipo Array pero implementa la interfaz ICollection<T>.

  • El tipo de tiempo de ejecución de un resultado de expresión es un tipo de valor que acepta valores NULL con el tipo T subyacente.
  • Existe una conversión boxing o unboxing del tipo de tiempo de ejecución de un resultado de expresión al tipo T.
El siguiente ejemplo demuestra las dos últimas condiciones:

int? xNullable = 7;
int y = 23;
object yBoxed = y;
if (xNullable is int a && yBoxed is int b)
{
    Console.WriteLine(a + b);  // output: 30
}

Si desea verificar solo el tipo de una expresión, puede usar un descarte _ en lugar del nombre de una variable, como muestra el siguiente ejemplo:

public abstract class Vehicle {}
public class Car : Vehicle {}
public class Truck : Vehicle {}

public static class TollCalculator
{
    public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch
    {
        Car _ => 2.00m,
        Truck _ => 7.50m,
        null => throw new ArgumentNullException(nameof(vehicle)),
        _ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)),
    };
}

A partir de C# 9.0, para ello puede utilizar un patrón de tipo, como muestra el siguiente ejemplo:

public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch
{
    Car => 2.00m,
    Truck => 7.50m,
    null => throw new ArgumentNullException(nameof(vehicle)),
    _ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)),
};


Al igual que un patrón de declaración, un patrón de tipo coincide con una expresión cuando el resultado de una expresión no es nulo y su tipo de tiempo de ejecución satisface cualquiera de las condiciones enumeradas anteriormente.

Para verificar si no es nulo, puede usar un patrón constante nulo negado, como muestra el siguiente ejemplo:

if (input is not null)
{
    // ...
}

Bueno, hasta acá con la declaración, en post posteriores seguire con los demas puntos. 


lunes, 9 de enero de 2023

¿Cuál es la diferencia entre openSUSE Leap y Tumbleweed?


En un post posterior, voy a contarles que estoy probando OpenSuse, lo que sucedio es que a la hora de bajarlo, me preguntaba cual quería si Leap o Tumbleweed. Y que se yo? no tenia idea en que radicaba la diferencia. Por lo tanto, decidí investigar un poco y dejo lo que encontré aquí, 

La principal diferencia entre los dos es el calendario de lanzamiento. openSUSE Leap lanza una nueva versión cada pocos años en un horario establecido, similar a Ubuntu y Fedora. Tumbleweed, por otro lado, es una versión móvil que, como Arch o Void, sigue el ciclo de desarrollo de openSUSE.

Conclusión si te interesa tener lo ultimo que salio rápidamente Tumbleweed y si te interesa la estabilidad Leap. 

Y eso es todo... 

sábado, 7 de enero de 2023

Foldable y Traverse parte 4

Cada método en Foldable está disponible en forma de sintaxis a través de cats.syntax.foldable. En cada caso, el primer argumento del método en Foldable se convierte en el receptor de la llamada al método:


import cats.syntax.foldable._ // for combineAll and foldMap

List(1, 2, 3).combineAll

// res12: Int = 6

List(1, 2, 3).foldMap(_.toString)

// res13: String = "123"


Recuerde que Scala solo usará una instancia de Foldable si el método no está explícitamente disponible en el receptor. Por ejemplo, el siguiente código usará la versión de foldLeft definida en List:


List(1, 2, 3).foldLeft(0)(_ + _)

// res14: Int = 6


mientras que el siguiente código genérico utilizará Foldable:


def sum[F[_]: Foldable](values: F[Int]): Int = values.foldLeft(0)(_ + _)


Por lo general, no necesitamos preocuparnos por esta distinción. ¡Es una característica! Llamamos al método que queremos y el compilador usa un Foldable cuando es necesario para garantizar que nuestro código funcione como se espera. Si necesitamos una implementación segura de pila de foldRight, usar Eval como acumulador es suficiente para obligar al compilador a seleccionar el método de Cats.


viernes, 6 de enero de 2023

Probando linux zorin

Sigo probando linux y ahora estoy probando Zorin y para ser sincero, no me gusto. No encuentro mucha diferencias con ubuntu, es más no entiendo porque una persona elegiría esta distro, no aporta casi nada nuevo. Ojo estoy probando la versión gratuita. 

Es decir, es linda distro, esta bueno el menú, los temas y las demás aplicaciones pero no brinda un salto a algo diferente, se queda con retoques a ubuntu y nada más. 

Pero bueno, véanlo por ustedes mismos: 









Dejo link: https://zorin.com/os/


miércoles, 4 de enero de 2023

Uso de Roslyn C# Completion Service programáticamente


Roslyn es un compilador C# como servicio seria CaaS 

El CompletionService de Roslyn inicialmente no estaba disponible públicamente, y la única forma de lograr mediante programación una experiencia similar a Intellisense era utilizar el servicio de recomendación bastante limitado. CompletionService finalmente se expuso públicamente en Roslyn 1.3.0.

Vamos a hacer un ejemplo para ver lo poderoso que puede ser esto. Para empezar, necesitaremos hacer referencia a 2 paquetes de Roslyn Nuget, como se muestra a continuación (nuestro archivo csproj de prueba):


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>

    <OutputType>Exe</OutputType>

    <LangVersion>latest</LangVersion>

    <TargetFramework>netcoreapp2.1</TargetFramework>

  </PropertyGroup>


  <ItemGroup>

    <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Features" Version="2.10.0" />

    <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="2.10.0" />

  </ItemGroup>

</Project>


Y necesitamos algún código para probar nuestras funciones, el siguiente ejemplo sirve: 


using System;


public class MyClass

{

    public static void MyMethod(int value)

    {

        Guid.

    }

}


Entonces, si imaginamos la experiencia del usuario aquí, nos ponemos en el lugar del usuario, escribimos Guid, presionamos un . carácter y ahora están esperando todos los métodos relevantes en este contexto particular.

En Visual Studio/Visual Studio Code (a través de OmniSharp), esta lista se mostraría automáticamente. En caso de que se haya cerrado, por ejemplo, al presionar la tecla ESC, siempre puede volver a activarlo presionando ctrl+j (VS) o ctrl/cmd+espacio (VS Code).

Para empezar, conectemos los servicios MEF de Roslyn, ya que deben completarse para que los servicios del lenguaje C# funcionen correctamente.

La forma más fácil es simplemente usar el conjunto predeterminado:

var host = MefHostServices.Create(MefHostServices.DefaultAssemblies);

Los siguientes asemblies están incluidos en el conjunto predeterminado:

  • “Microsoft.CodeAnalysis.Workspaces”,
  • “Microsoft.CodeAnalysis.CSharp.Workspaces”,
  • “Microsoft.CodeAnalysis.VisualBasic.Workspaces”,
  • “Microsoft.CodeAnalysis.Features”,
  • “Microsoft.CodeAnalysis.CSharp.Features”,
  • “Microsoft.CodeAnalysis.VisualBasic.Features”
  • Si tiene alguna extensión para Roslyn o características personalizadas de Roslyn de terceros que le gustaría incluir, deberá pasar esos ensamblajes adicionales manualmente.

    Una vez que los servicios de MEF están conectados, el siguiente paso es crear un espacio de trabajo. En esta demostración, solo usaremos un AdHocWorkspace.

    Para escenarios más complicados, como, por ejemplo, poder proporcionar inteligencia completa a una solución del mundo real o proyecto (s) de csproj, deberíamos de usar Microsoft.CodeAnalysis.Workspaces.MSBuild 

    Así que para nosotros el código será bastante simple:

    var workspace = new AdhocWorkspace(host);

    Una vez que el espacio de trabajo está allí, debemos crear un documento que contenga nuestro código y luego un proyecto al que agregaremos nuestro documento (o documentos, si tenemos más). Luego, el proyecto debe agregarse al espacio de trabajo. Nuevamente, en el caso de MsBuildWorkspace, esto se puede hacer automáticamente leyendo los archivos del proyecto y su estructura.

    En nuestro ejemplo, las cosas se verían así:


    var code = @"using System;


    public class MyClass

    {

        public static void MyMethod(int value)

        {

            Guid.

        }

    }";


    var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Create(), "MyProject", "MyProject", LanguageNames.CSharp).

       WithMetadataReferences(new[]

       { 

           MetadataReference.CreateFromFile(typeof(object).Assembly.Location)

       });

    var project = workspace.AddProject(projectInfo);

    var document = workspace.AddDocument(project.Id, "MyFile.cs", SourceText.From(code));


    Para crear un proyecto, primero creamos un ProjectInfo, donde debemos pasar cosas como el nombre del proyecto, el nombre del ensamblado (en nuestro caso, "MyProject"), el tipo de lenguaje y un par de cosas más relevantes para la compilación, principalmente las MetadataReferences necesarias para que se construya nuestro código. En nuestro caso, es realmente solo el corlib, o en otras palabras, el ensamblaje del objeto.

    Se crea una instancia de Proyecto para nosotros como resultado de agregar ProjectInfo al espacio de trabajo. De manera similar, también se crea una instancia de documento para nosotros cuando solicitamos que se agregue un código basado en cadenas determinado al área de trabajo, en el contexto de una ID de proyecto determinada.

    Una vez que tenemos el Documento que es parte del Área de trabajo, podemos comenzar a usar el Servicio. Tiene un método de fábrica que podemos usar, y solo necesitamos pasar en la posición relevante en el código (para nosotros Guid.) para que las terminaciones comiencen a aparecer:


    // position is the last occurrence of "Guid." in our test code

    // in real life scenarios the editor surface should inform us

    // about the current cursor position

    var position = code.LastIndexOf("Guid.") + 5;

    var completionService = CompletionService.GetService(document);

    var results = await completionService.GetCompletionsAsync(document, position);


    En ese punto obtenemos nulo si no hay finalizaciones que tengan sentido para el compilador, o una buena lista de elementos de finalizaciones que podemos inspeccionar y mostrar al usuario.

    Los elementos se agrupan en diferentes categorías, representadas por etiquetas. Esto puede ayudar al editor a visualizar con qué tipo de elemento de finalización se trata. Estos podrían ser, por ejemplo, el tipo de símbolo (campo, método, etc.), el nivel de accesibilidad (público, interno, etc.) o cualquier otra información (¿es una palabra clave del lenguaje? ¿Quizás por un parámetro en el ámbito dado? etc.).

    Cada elemento de finalización se nos proporciona con DisplayText, que el editor debe usar para presentar la sugerencia al usuario, y SortText, que se puede usar para clasificar, así como otros metadatos útiles adicionales.

    Cada elemento de finalización se origina en un determinado CompletionProvider, porque el propio servicio de finalización en realidad agrega los resultados de un conjunto de esos proveedores que están conectados al host MEF. Algunos de ellos son muy especializados, por ejemplo, OverrideCompletionProvider, que permite proporcionar terminaciones cuando el usuario escribe anular.

    Dado que CompletionProvider es público, también puede implementar el suyo propio y personalizar completamente el proceso de finalización en Roslyn.

    De todos modos, por ahora, imprimamos lo que obtuvimos de Roslyn en esta configuración de demostración en particular. 


    foreach (var i in results.Items)

    {

        Console.WriteLine(i.DisplayText);


        foreach (var prop in i.Properties)

        {

            Console.Write($"{prop.Key}:{prop.Value}  ");

        }


        Console.WriteLine();

        foreach (var tag in i.Tags)

        {

            Console.Write($"{tag}  ");

        }


        Console.WriteLine();

        Console.WriteLine();

    }


    Si ejecutamos nuestro programa ahora, la salida debería verse así:


    Empty

    ContextPosition:166  SymbolKind:6  InsertionText:Empty  Provider:Microsoft.CodeAnalysis.CSharp.Completion.Providers.SymbolCompletionProvider  SymbolName:Empty

    Field  Public


    Equals

    ContextPosition:166  SymbolKind:9  InsertionText:Equals  Provider:Microsoft.CodeAnalysis.CSharp.Completion.Providers.SymbolCompletionProvider  SymbolName:Equals

    Method  Public


    NewGuid

    ContextPosition:166  SymbolKind:9  InsertionText:NewGuid  Provider:Microsoft.CodeAnalysis.CSharp.Completion.Providers.SymbolCompletionProvider  SymbolName:NewGuid

    Method  Public


    Parse

    ContextPosition:166  SymbolKind:9  InsertionText:Parse  Provider:Microsoft.CodeAnalysis.CSharp.Completion.Providers.SymbolCompletionProvider  SymbolName:Parse

    Method  Public


    ParseExact

    ContextPosition:166  SymbolKind:9  InsertionText:ParseExact  Provider:Microsoft.CodeAnalysis.CSharp.Completion.Providers.SymbolCompletionProvider  SymbolName:ParseExact

    Method  Public


    ReferenceEquals

    ContextPosition:166  SymbolKind:9  InsertionText:ReferenceEquals  Provider:Microsoft.CodeAnalysis.CSharp.Completion.Providers.SymbolCompletionProvider  SymbolName:ReferenceEquals

    Method  Public


    TryParse

    ContextPosition:166  SymbolKind:9  InsertionText:TryParse  Provider:Microsoft.CodeAnalysis.CSharp.Completion.Providers.SymbolCompletionProvider  SymbolName:TryParse

    Method  Public


    TryParseExact

    ContextPosition:166  SymbolKind:9  InsertionText:TryParseExact  Provider:Microsoft.CodeAnalysis.CSharp.Completion.Providers.SymbolCompletionProvider  SymbolName:TryParseExact

    Method  Public


    Tenga en cuenta que obtenemos todos los métodos/propiedades/campos relevantes que esperaríamos. Cada elemento de finalización tiene la información adicional en las etiquetas. Además, hay algunos metadatos adicionales en el diccionario de propiedades, como por ejemplo el tipo de proveedor que se usó para proporcionar esta finalización (aunque en nuestro caso, todos terminan siendo de SymbolCompletionProvider).

    Hasta ahora, el enfoque se basaba en código C# completo. Esto funciona para la mayoría de los escenarios, sin embargo, para situaciones en las que no se trata de proyectos de C# completos o archivos de código, sino que le gustaría completar fragmentos ligeros, no sería aplicable.

    Imagine que queremos obtener exactamente el mismo conjunto de resultados de finalización que el anterior, pero ya cuando el usuario simplemente escribió:

    Guid.

    Entonces, sin clase, sin método, sin usos, solo 5 caracteres. Esto es especialmente atractivo para experiencias similares a REPL o pequeños fragmentos de código incrustados en alguna parte.

    Resulta que este nivel de finalización también se puede lograr con Roslyn, cuando pasamos a su modo de "guión".

    Fundamentalmente, nuestro código sería el mismo, crearíamos el host MEF y el espacio de trabajo de la misma manera. Sin embargo, al crear el Proyecto y el Documento, debemos decirle al compilador que analice nuestro código como el llamado SourceCodeKind.Script. Esto se muestra a continuación:


    var scriptCode = "Guid.N";


    var compilationOptions = new CSharpCompilationOptions(

       OutputKind.DynamicallyLinkedLibrary,

       usings: new[] { "System" });

                       

    var scriptProjectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Create(), "Script", "Script", LanguageNames.CSharp, isSubmission: true)

       .WithMetadataReferences(new[] 

       { 

           MetadataReference.CreateFromFile(typeof(object).Assembly.Location) 

       })

       .WithCompilationOptions(compilationOptions);


    var scriptProject = workspace.AddProject(scriptProjectInfo);

    var scriptDocumentInfo = DocumentInfo.Create(

        DocumentId.CreateNewId(scriptProject.Id), "Script",

        sourceCodeKind: SourceCodeKind.Script,

        loader: TextLoader.From(TextAndVersion.Create(SourceText.From(scriptCode), VersionStamp.Create())));

    var scriptDocument = workspace.AddDocument(scriptDocumentInfo);


    // cursor position is at the end

    var position = scriptCode.Length - 1;


    var completionService = CompletionService.GetService(scriptDocument);

    var results = await completionService.GetCompletionsAsync(scriptDocument, position);


    Las API que llamamos son en su mayoría las mismas, con las mismas pequeñas diferencias que son las siguientes:

    – necesitamos crear una versión personalizada de CSharpCompilationOptions, que luego pasamos a nuestro ProjectInfo. Esto es necesario para que configuremos un proyecto con un conjunto global de instrucciones de uso. En nuestro caso, es solo System (para que el usuario no tenga que escribir System.Guid.), pero podría ser más para permitir esta experiencia de finalización sin importación para una gama más amplia de tipos.

    – al crear nuestro Documento, configuramos un DocumentInfo extra. La relación entre ellos es la misma que entre Project y ProjectInfo. Esto será necesario para pasar del analizador C# normal al script. Nos permitirá procesar nuestro código sintácticamente relajado sin encontrarnos con los errores del compilador que de otro modo nos bloquearían.

    Y eso es todo: el resultado aquí es exactamente el mismo que antes, excepto que logramos proporcionar las terminaciones utilizando la entrada de C# de una sola línea, liviana y de poca ceremonia, que creo que es bastante impresionante.

    Espero que esto haya sido interesante, y tal vez incluso un poco útil. Avíseme si desea profundizar en este tema o conocer otros componentes básicos de Roslyn, especialmente en el área de servicios de lenguaje C#.

    martes, 3 de enero de 2023

    Echo, Framework web de alto rendimiento, extensible y minimalista para Golang


    Echo, es un framework web para golang que nos brinda : 

    • Enrutador HTTP altamente optimizado con asignación de memoria dinámica cero que prioriza rutas de manera inteligente.
    • Creación de un API RESTful robusta y escalable, fácilmente organizada en grupos.
    • Se puede instalar automáticamente certificados TLS de Let's Encrypt.
    • La compatibilidad con HTTP/2 mejora la velocidad y proporciona una mejor experiencia de usuario.
    • Muchos middleware integrados para usar o definir el suyo propio. El middleware se puede configurar a nivel de raíz, grupo o ruta.
    • Enlace de datos para la carga útil de la solicitud HTTP, incluidos JSON, XML o datos de formulario.
    • API para enviar una variedad de respuestas HTTP, incluidos JSON, XML, HTML, archivo, adjunto, en línea, flujo o blob.
    • Representación de plantillas utilizando cualquier motor de plantillas
    • Manejo de errores HTTP central personalizado. API fácilmente extensible.


    Muy lindo todo pero la idea es hacer un hola mundo, veamos. 


    Para instalar se requiere Echo Go v1.13 o superior. Go v1.12 tiene soporte limitado y algunos middlewares no estarán disponibles. Asegúrese de que la carpeta de su proyecto esté fuera de su $GOPATH.


    $ mkdir myapp && cd myapp

    $ go mod init myapp

    $ go get github.com/labstack/echo/v4


    Si está trabajando con Go v1.14 o anterior, use:


    $ GO111MODULE=on go get github.com/labstack/echo/v4

    Veamos exponer un servicio enel golang : 

    package main

    import (
    "net/http"
    "github.com/labstack/echo/v4"
    )

    func main() {
    e := echo.New()
    e.GET("/", func(c echo.Context) error {
    return c.String(http.StatusOK, "Hello, World!")
    })
    e.Logger.Fatal(e.Start(":1323"))
    }

    Y lo corremos de esta manera : 

    $ go run server.go

    Dejo link: https://echo.labstack.com/