Translate
jueves, 4 de enero de 2018
10 ebook populares del 2017
Me llego este mail y como la mayoría de los libros son gratuitos, lo quiero compartir:
miércoles, 3 de enero de 2018
Comparando F# con C# parte 2
Ahora, implementaremos un el algoritmo quicksort para ordenar listas y lo haremos en F# y C# para compararlos.
Para el que no conoce el algoritmo quicksort, vamos a ver la lógica:
Si la lista está vacía, no hay nada que hacer.
De otra manera:
- Tome el primer elemento de la lista, que lo llamaremos pivot
- Buscamos todos los elementos menores al pivot y los ordenamos usando el algoritmo quicksort.
- Buscamos todos los elementos mayores al pivot y los ordenamos usando el algoritmo quicksort.
- Combinamos las tres partes para obtener el resultado final: (elementos menores + pivot + elementos mayores)
Tenga en cuenta que hemos simplificado este algoritmo para hacer la explicación más simple.
Veamos el código en F#:
let rec quicksort list =
match list with
| [] -> // Si la lista es vacia
[] // retorna una lista vacia
| firstElem::otherElements -> // si no es vacia
let smallerElements = // toma los menores
otherElements
|> List.filter (fun e -> e < firstElem)
|> quicksort // y los ordena
let largerElements = // toma los mayores
otherElements
|> List.filter (fun e -> e >= firstElem)
|> quicksort // y los ordena
// concatena estas 3 partes y la retorna.
List.concat [smallerElements; [firstElem]; largerElements]
//test
printfn "%A" (quicksort [1;5;23;18;9;1;3])
Repasemos el código:
No hay declaraciones de tipos en ningún lado. Esta función funcionará en cualquier lista que tenga elementos comparables (que es casi todos los tipos F#, ya que automáticamente tienen una función de comparación predeterminada).
Toda la función es recursiva: esto se señala al compilador utilizando la palabra clave rec en "let rec quicksort list =".
Con match..with se esta usando pattern matching, las expresiones son como esta:
match x with
| caseA -> something
| caseB -> somethingElse
El pattern matching es una técnica que analiza objetos y ejecuta el código que corresponde (cuando el objeto aplica le patron)
De esta manera se pregunta si la lista es vacía, y si es vacía se retorna una lista vacía.
De lo contrario, aplica la lógica descrita anteriormente. Es decir filtra la lista de los menores por medio de una función anónima que se pasa como clausura, que indica como se va a filtrar y luego se ordena utilizando quicksort, luego filtra la lista de los mayores y los ordena . Y por ultimo se retorna la concatenación de estas 3 partes. ,
Veamos la implementación en C# sin LinQ :
public class QuickSortHelper
{
public static List<T> QuickSort<T>(List<T> values)
where T : IComparable
{
if (values.Count == 0)
{
return new List<T>();
}
// Tomamos el primer valor
T firstElement = values[0];
// Filtramos los elementos
var smallerElements = new List<T>();
var largerElements = new List<T>();
for (int i = 1; i < values.Count; i++) {
var elem = values[i];
if (elem.CompareTo(firstElement) < 0)
{
smallerElements.Add(elem);
}
else
{
largerElements.Add(elem);
}
}
result.AddRange(QuickSort(smallerElements.ToList()));
result.Add(firstElement);
result.AddRange(QuickSort(largerElements.ToList()));
return result;
}
}
Comparando los dos programas, nuevamente podemos ver que el código F# es mucho más compacto, con menos ruido y sin necesidad de declaraciones de tipo.
Además, el código F# se lee casi exactamente como es algoritmo, a diferencia del código C#. Esta es otra ventaja clave de F# - el código es generalmente más declarativo ("qué hacer") y menos imperativo ("cómo hacerlo") que C#, y por lo tanto es mucho más autodocumentado.
Veamos una versión más funcional en C#:
public static class QuickSortExtension
{
public static IEnumerable<T> QuickSort<T>(
this IEnumerable<T> values) where T : IComparable
{
if (values == null || !values.Any())
{
return new List<T>();
}
var rest = values.Skip(1);
.Where(i => i.CompareTo(firstElement) < 0)
.QuickSort();
var largerElements = rest
.Where(i => i.CompareTo(firstElement) >= 0)
.QuickSort();
return smallerElements
.Concat(new List<T>{firstElement})
.Concat(largerElements);
}
}
Esto es mucho más limpio, y lee casi lo mismo que la versión F#.
Finalmente, el código F# a menudo funciona la primera vez, mientras que el código C# puede requerir más depuración.
Pero incluso la ultima versión funcional C# tiene inconvenientes en comparación con la versión F#. Por ejemplo, como F# usa la coincidencia de patrones, no es posible derivar al caso de la "lista no vacía" con una lista vacía.
Dejo link: https://fsharpforfunandprofit.com/posts/fvsc-quicksort/
No hay declaraciones de tipos en ningún lado. Esta función funcionará en cualquier lista que tenga elementos comparables (que es casi todos los tipos F#, ya que automáticamente tienen una función de comparación predeterminada).
Toda la función es recursiva: esto se señala al compilador utilizando la palabra clave rec en "let rec quicksort list =".
Con match..with se esta usando pattern matching, las expresiones son como esta:
match x with
| caseA -> something
| caseB -> somethingElse
El pattern matching es una técnica que analiza objetos y ejecuta el código que corresponde (cuando el objeto aplica le patron)
De esta manera se pregunta si la lista es vacía, y si es vacía se retorna una lista vacía.
De lo contrario, aplica la lógica descrita anteriormente. Es decir filtra la lista de los menores por medio de una función anónima que se pasa como clausura, que indica como se va a filtrar y luego se ordena utilizando quicksort, luego filtra la lista de los mayores y los ordena . Y por ultimo se retorna la concatenación de estas 3 partes. ,
Veamos la implementación en C# sin LinQ :
public class QuickSortHelper
{
public static List<T> QuickSort<T>(List<T> values)
where T : IComparable
{
if (values.Count == 0)
{
return new List<T>();
}
// Tomamos el primer valor
T firstElement = values[0];
// Filtramos los elementos
var smallerElements = new List<T>();
var largerElements = new List<T>();
for (int i = 1; i < values.Count; i++) {
var elem = values[i];
if (elem.CompareTo(firstElement) < 0)
{
smallerElements.Add(elem);
}
else
{
largerElements.Add(elem);
}
}
result.AddRange(QuickSort(smallerElements.ToList()));
result.Add(firstElement);
result.AddRange(QuickSort(largerElements.ToList()));
return result;
}
}
Comparando los dos programas, nuevamente podemos ver que el código F# es mucho más compacto, con menos ruido y sin necesidad de declaraciones de tipo.
Además, el código F# se lee casi exactamente como es algoritmo, a diferencia del código C#. Esta es otra ventaja clave de F# - el código es generalmente más declarativo ("qué hacer") y menos imperativo ("cómo hacerlo") que C#, y por lo tanto es mucho más autodocumentado.
public static class QuickSortExtension
{
public static IEnumerable<T> QuickSort<T>(
this IEnumerable<T> values) where T : IComparable
{
if (values == null || !values.Any())
{
return new List<T>();
}
var rest = values.Skip(1);
.Where(i => i.CompareTo(firstElement) < 0)
.QuickSort();
var largerElements = rest
.Where(i => i.CompareTo(firstElement) >= 0)
.QuickSort();
return smallerElements
.Concat(new List<T>{firstElement})
.Concat(largerElements);
}
}
Esto es mucho más limpio, y lee casi lo mismo que la versión F#.
Finalmente, el código F# a menudo funciona la primera vez, mientras que el código C# puede requerir más depuración.
Pero incluso la ultima versión funcional C# tiene inconvenientes en comparación con la versión F#. Por ejemplo, como F# usa la coincidencia de patrones, no es posible derivar al caso de la "lista no vacía" con una lista vacía.
Dejo link: https://fsharpforfunandprofit.com/posts/fvsc-quicksort/
lunes, 1 de enero de 2018
Diferencia entre ArrayList y LinkedList en Java
Este post lo podría haber hecho hace mucho pero bueno hace poco que me he dado cuenta que esto no es de conocimiento de todos los mortales programadores java.
Antes que nada aclaro que tanto ArrayList como LinkedList implementan la interfaz List y se encuentran en el paquete java.util y son parte de lo que se conoce como java collection framework o jcf para los amigos.
La principal diferencia es un tema de implementación ArrayList implementa la lista con arreglos linkeados, lo que la hace muy eficiente para recorrer pero ineficiente para insertar o eliminar elementos que se no encuentren en el final. En cambio LinkedList es una lista de elementos linkeados (en realidad es una lista doblemente enlazada) lo que la hace lenta para recorrer pero sumamente eficiente para insertar o eliminar elementos. Esta es la principal diferencia y hay que recordarla siempre.
Por lo tanto ArrayList :
- usa internamente un arreglo dinámico para almacenar los elementos.
- proporciona una manipulación lenta
- es la mejor opción para almacenar y acceder a datos o elementos consecutivos.
Por lo tanto LinkedList:
- proporciona una manipulación más rápida porque utiliza una lista doblemente enlazada.
- se puede utilizar como lista y cola porque implementa interfaz de List, Deque y Queue.
- es mejor para manipulación de elementos, es decir, para insertar y eliminar elementos.
Por lo tanto si necesitamos agregar elementos consecutivos y recorrerlos debemos utilizar ArrayList y si en cambio necesitamos insertar y eliminar valores no consecutivos debemos usar LinkedList.
Veamos un ejemplo de ArrayList:
import java.util.*;
public class Sample {
public static void main(String args[]) {
//Declaring ArrayList
List<String> l = new ArrayList<String>();
l.add("Apple");//inserting elements
l.add("Orange");
l.add("Mango");
l.add("Banana");
l.add("Guava");
//Traverse the elements by using Iterator interface
Iterator i = l.iterator();
while(i.hasNext()) {
System.out.println(i.next());
}
}
}
Output: Apple
Orange
Mango
Banana
Guava
Veamos un ejemplo de LinkedList:
import java.util.*;
public class Demo {
public static void main(String args[]) {
//Declaring the LinkedList
LinkedList<String> ll = new LinkedList<String>();
ll.add("Red");
ll.add("Red");
ll.add("Black")';
ll.add("Blue");
ll.add("Pink");
ll.add("Green");
//Traversing elements by using Iterator interface
Iterator i = ll.iterator();
while(i.hasNext()) {
System.out.println(i.next())
}
}
}
Output: Red
Red
Black
Blue
Pink
Green
Dejo link:
domingo, 31 de diciembre de 2017
Feliz 2018 !!!
Feliz 2018, que todos tus sueños se cumplan, que aprendas mucho y que enseñes aun más.
Gracias por leer!!
sábado, 30 de diciembre de 2017
StringJoiner la nueva clase en Java 8
Java 8 se viene con todo y ahora vamos a ver la clase StringJoiner. Para que sirve? como su nombre lo indica se utiliza para construir una secuencia de caracteres separados por delimitadores, es decir, puede crear cadenas utilizando algunos delimitadores como "," (coma) y "-" (guión), etc. También podemos usar prefijos y sufijos para la secuencia de caracteres.
StringJoiner se encuentra en el paquete java.util y es una clase que es final y extiende de object.
Tiene 2 constructores:
- StringJoiner(CharSequence delimiter).
- StringJoiner(CharSequence delimiter, CharSequence prefix, CharSequence suffix).
En el primero solo le pasamos el delimitador y en el segundo le pasamos el delimitador, el prefijo y sufijo de la cadena que vamos a formar.
Entre los métodos más importantes podemos nombrar:
- StringJoiner add(CharSequence newElement) : Agrega un elemento
- int length() : cantidad de caracteres.
- StringJoiner merge(StringJoiner other): une 2 secuencias.
- StringJoiner setEmptyValue(CharSequence emptyValue) : Definimos que valor va a retornar si la secuencia en vacía.
- String toString() : Retorna la cadena
Veamos unos ejemplos:
import java.util.*;
class Demo {
public static void main(String args[]) {
StringJoiner sj = new StringJoiner(",");//passing comma (,) as delimiter
StringJoiner sj1 = new StringJoiner("-");//passing hyphen (-) as delimiter
//Adding some string with comma(,) delimiter
sj.add("suresh");
sj.add("gurpreet");
sj.add("piyush");
sj.add("jagdish");
System.out.println(sj);
System.out.println();
//Adding some string with hyphen(-) delimiter
sj1.add("simran");
sj1.add("siya");
sj1.add("khusboo");
sj1.add("barkha");
System.out.println(sj1);
}
}
Output: suresh,gurpreet,piyush,jagdish
simran-siya-khusboo-barkha
Recordemos que System.out.println utiliza el metodo toString para imprimir un objeto.
Veamos un ejemplo con sufijo y prefijo:
import java.util.StringJoiner;
class Demo1 {
public static void main(String args[]) {
//passing , as delimiter and using "(" opening bracket as prefix and ")" closing bracket as suffix.
StringJoiner sj = new StringJoiner(",","(",")");
sj.add("blue");
sj.add("red");
sj.add("pink");
sj.add("white");
System.out.println(sj);
}
}
Output: (blue,red,pink,white)
Veamos ahora un ejemplo con merge:
import java.util.*;
class Demo3 {
public static void main(String args[]) {
//Creating first StringJoiner with delimiter and prefix and suffix
StringJoiner sj1 = new StringJoiner(",","*","*");
sj1.add("rose");
sj1.add("lotus");
System.out.println(sj1);
//Creating second StringJoiner with delimiter and prefix and suffix
StringJoiner sj2 = new StringJoiner(":","*","*");
sj2.add("red");
sj2.add("pink");
System.out.println(sj2);
//Now using merge() method for merging sj1 and sj2 joiners
StringJoiner mrg = sj1.merge(sj2);
System.out.println(mrg);
}
}
Output: *rose,lotus*
*red:pink*
*rose,lous,red:pink*
Y por ultimo un ejemplo integrador:
import java.util.*;
class Demo4 {
public static void main(String args[]){
StringJoiner sj1 = new StringJoiner(",");
/* if StringJoiner is empty then we can print a massage for this StringJoiner by using setEmptyValue(). */
sj1.setEmptyValue("This is empty StringJoiner");
System.out.println(sj1);
System.out.println("add some values");
//now adding some string by using add() method
sj1.add("c++");
sj1.add("html");
System.out.println("added values is: "+sj1);
//After adding values, let's count the length of string by using length() method
int length = sj1.length();
System.out.println("Length of SJ "+length);
}
}
Output: This is empty StringJoiner
add some values
added values is: c++,html
Length of SJ 8
viernes, 29 de diciembre de 2017
Comparando F# con C#
Vamos a comparar C# con F# a traves de un ejemplo, una suma simple. El problema es simple: "sumar los cuadrados de 1 a N".
Primero, veamos el código F# :
// define the square function
let square x = x * x
// define the sumOfSquares function
let sumOfSquares n =
[1..n] |> List.map square |> List.sum
// try it
sumOfSquares 100
Y listo, como podemos ver podemos utilizar el operador |> para que la salida de una función, sea entrada de otra. Es similar a el operador |> de elixir.
Si vemos la linea: let sumOfSquares n = [1..n] |> List.map square |> List.sum
- Crea una lista de enteros de 1 a n.
- Luego toma esa lista y aplica una función square usando la biblioteca llamada List.map.
- Luego acumula todos los elementos de la lista resultante.
Ahora veamos una implementación en C# utilizando el estilo clásico (no funcional) :
public static class SumOfSquaresHelper
{
public static int Square(int i)
{
return i * i;
}
public static int SumOfSquares(int n)
{
int sum = 0;
for (int i = 1; i <= n; i++)
{
sum += Square(i);
}
return sum;
}
}
¿Cuáles son las diferencias?
- El código F# es más compacto
- El código F# no tenía ninguna declaración de tipo
- Con F# podemos desarrollar interactivamente
La diferencia más obvia es que hay mucho más código C#. 13 líneas en C# en comparación con 3 líneas en F# (ignorando los comentarios). El código C# tiene mucho "ruido", cosas como llaves, puntos y comas, etc. Y en C# las funciones no pueden estar solas, sino que deben agregarse a alguna clase ("SumOfSquaresHelper"). F# usa espacios en blanco en lugar de paréntesis, no necesita terminador de línea y las funciones pueden ser independientes.
En F#, es común que las funciones completas se escriban en una línea, como la función "cuadrada". La función sumOfSquares también podría haber sido escrita en una línea. En C# esto es mal visto y es considerado una mala práctica.
Cuando una función tiene múltiples líneas, F# usa indentación para indicar un bloque de código, lo que elimina la necesidad de llaves. (Si alguna vez ha usado Python, esta es la misma idea). Entonces la función sumOfSquares también podría haber sido escrita de esta manera:
let sumOfSquares n =
[1..n]
|> List.map square
|> List.sum
La siguiente diferencia es que el código C# tiene que declarar explícitamente todos los tipos utilizados. Por ejemplo, el parámetro n es de tipo int y el tipo de retorno SumOfSquares es int. Sí bien, C# permite usar la palabra clave "var" en muchos lugares, pero no para los parámetros y tampoco para tipos de funciones.
En el código F#, no declaramos ningún tipo. Este es un punto importante: F# parece un lenguaje sin tipo o de tipado dinámico, pero en realidad es igual de seguro que C#, de hecho, ¡aún más! F# usa una técnica llamada "inferencia de tipo" para inferir los tipos que está utilizando desde su contexto. Funciona increíblemente bien la mayor parte del tiempo, y reduce la complejidad del código inmensamente.
En este caso, el algoritmo de inferencia de tipo observa que comenzamos con una lista de enteros. Esto a su vez implica que la función cuadrada y la función suma también deben tomarse, y que el valor final debe ser un int. Puede ver cuáles son los tipos inferidos mirando el resultado de la compilación en la ventana interactiva. Verás algo como:
val square : int -> int
lo que significa que la función "cuadrado" toma un int y devuelve un int. Esta notación me recuerda mucho a Haskell o Scala.
Si la lista original hubiera utilizado flotantes en su lugar, el sistema de inferencia tipo habría deducido que la función cuadrada utilizada flotantes en su lugar:
// define the square function
let squareF x = x * x
// define the sumOfSquares function
let sumOfSquaresF n =
[1.0 .. n] |> List.map squareF |> List.sum // "1.0" is a float
sumOfSquaresF 100.0
¡La verificación de tipos es muy estricta! Si intenta usar una lista de flotantes ([1.0..n]) en el ejemplo original sumOfSquares, o una lista de ints ([1 ..n]) en el ejemplo sumOfSquaresF, obtendrá un error de tipo del compilador.
Finalmente, F# tiene una ventana interactiva donde puedes probar el código inmediatamente y jugar con él. En C# no hay una manera fácil de hacer esto.
Por ejemplo, puedo escribir mi función cuadrada e inmediatamente probarla:
// define the square function
let square x = x * x
// test
let s2 = square 2
let s3 = square 3
let s4 = square 4
Muchas personas afirman que el diseño de códigos impone de forma interactiva buenas prácticas de diseño, como el desacoplamiento y las dependencias explícitas, y por lo tanto, el código que es adecuado para la evaluación interactiva también será un código que es fácil de probar. Por el contrario, el código que no se puede probar de forma interactiva probablemente también sea difícil de probar.
El ejemplo anterior fue escrito usando C# viejo. C# ha incorporado muchas características funcionales, y es posible reescribir el ejemplo de una manera más compacta utilizando las extensiones LINQ.
Así que aquí hay otra versión C#:
public static class FunctionalSumOfSquaresHelper
{
public static int SumOfSquares(int n)
{
return Enumerable.Range(1, n)
.Select(i => i * i)
.Sum();
}
}
Sin embargo, además del ruido de las llaves, los puntos y los puntos y comas, la versión C# necesita declarar el parámetro y los tipos de retorno, a diferencia de la versión F#.
Si bien el ejemplo fue trivial, nos permitio revisar las deferencias entre F# y C#.
Dejo link: https://fsharpforfunandprofit.com/posts/fvsc-sum-of-squares//
miércoles, 27 de diciembre de 2017
Referencia a metodos en Java 8
Java 8 trae muchas mejoras, tal vez la más importante es que podemos utilizar clausuras o closures en ingles. Pero a la vez Java 8 trae una cantidad interesantes de métodos que utilizan esta nueva propiedad, y a la vez nos brindan mayor facilidad para resolver problemas.
La referencia del método Java 8 se usa para referirse a un método y para hacer que el programa o código sea simple o claro, puede usar la referencia al método en lugar de una expresión lambda.
En resumen esta notación abrevia la expresión lambda para llamar a cualquier método.
El operador '::' se usa como referencia de método. Veamos algunos tipos de referencias de método:
- Referencia a un método de una instancia: object :: instanceMethod
- Referencia a un método estático: Class :: staticMethod
- Referencia a un método de instancia de un objeto arbitrario de un tipo particular: Class :: instanceMethod
- Referencia a un constructor: Class :: new
En la siguiente imagen podemos ver la referencia y la expresión lambda que reemplaza:
Referencia a un método de una instancia:
@FunctionalInterface
interface Demo {
void show();
}
public class Test {
public void display() {
System.out.println("I am instance method");
}
public static void main(String args[]) {
Test t = new Test();
Demo d = t :: display;//performing method reference using object
d.show();//calling method of function interface
}
}
Output: I am instance method
Referencia a un método estático:
@FunctionalInterface
interface Demo1 {
void show();
}
class Test1 {
public static void display() {
System.out.println("Hi, i am static method of a class");
}
public static void main(String args[]) {
Demo1 dd = Test1 :: display;
dd.show();
}
}
Output: Hi, i am static method of a class
Referencia a un método de instancia de un objeto arbitrario de un tipo particular:
import java.util.Arrays;
class Test {
public static void main(String args[]) {
String str[] = {"pink", "orange", "black", "red"};
Arrays.sort(str, String :: compareToIgnoreCase);
for(String str1 : str) {
System.out.println(str1);
}
}
}
Output: black
orange
pink
red
Referencia a un constructor:
interface Demo4 {
FullName show(String s);
}
class FullName {
FullName(String s) {
System.out.println(s);
}
}
class Test {
public static void main(String args[]) {
Demo4 d = FullName :: new;//performing constructor reference
d.show("Anurag Singh");
}
}
Output: Anurag Singh
Dejo link: https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
martes, 26 de diciembre de 2017
Ordenar un arreglo en paralelo en Java 8
Java 8 trae muchas mejoras, tal vez la más importante es que podemos utilizar clausuras o closures en ingles. Pero a la vez Java 8 trae una cantidad interesantes de métodos que utilizan esta nueva propiedad, y a la vez nos brindan mayor facilidad para resolver problemas.
A la vez Java 8 proporciona una nueva característica que es ordenar un vector en paralelo. El método Arrays.sort() se usa para ordenar, pero java 8 proporciona un método nuevo que es el método parallelSort() para ordenar paralelamente los elementos de un vector.
El método parallelSort() pertenece a la clase Arrays, que está disponible en el paquete java.util. El método parallelSort() es más rápido que el método Array.sort() y este método sigue a fork / join framework para asignar las tareas de clasificación a varios subprocesos que están disponibles en el grupo de subprocesos. El método parallelSort () está sobrecargado para todos los tipos de datos primitivos y objetos que implementen Comparable<T>.
Veamos un simple ejemplo de como ordenar con este metodo:
import java.util.Arrays;
class ParallelSortExample
{
public static void main(String args[]) {
//Creamos un vector de enteros
int a[] = {50, 10, 90, 40, 80};
//Ahora los ordenamos
Arrays.parallelSort(a);
for(int i : a) {
System.out.println(i);
}
}
}
Output: 10
40
50
80
90
También podemos pasarle un Comparator que indique como debe ordenar, veamos un ejemplo:
package com.concretepage;
import java.util.Arrays;
import java.util.Comparator;
import java.util.function.Consumer;
public class ParallelSortWithComparator {
public static void main(String[] args) {
User[] users = User.getUsers();
Comparator<User> ageComparator = Comparator.comparing(User::getAge);
System.out.println("--Sort complete array--");
Arrays.parallelSort(users, ageComparator);
Consumer<User> printUser = u-> System.out.println(u.getName()+"-"+u.getAge());
Arrays.stream(users).forEach(printUser);
System.out.println("--Sort array from index 1 to 4--");
users = User.getUsers();
Arrays.parallelSort(users, 1, 4, ageComparator);
Arrays.stream(users).forEach(printUser);
}
}
A la vez Java 8 proporciona una nueva característica que es ordenar un vector en paralelo. El método Arrays.sort() se usa para ordenar, pero java 8 proporciona un método nuevo que es el método parallelSort() para ordenar paralelamente los elementos de un vector.
El método parallelSort() pertenece a la clase Arrays, que está disponible en el paquete java.util. El método parallelSort() es más rápido que el método Array.sort() y este método sigue a fork / join framework para asignar las tareas de clasificación a varios subprocesos que están disponibles en el grupo de subprocesos. El método parallelSort () está sobrecargado para todos los tipos de datos primitivos y objetos que implementen Comparable<T>.
Veamos un simple ejemplo de como ordenar con este metodo:
import java.util.Arrays;
class ParallelSortExample
{
public static void main(String args[]) {
//Creamos un vector de enteros
int a[] = {50, 10, 90, 40, 80};
//Ahora los ordenamos
Arrays.parallelSort(a);
for(int i : a) {
System.out.println(i);
}
}
}
Output: 10
40
50
80
90
También podemos pasarle un Comparator que indique como debe ordenar, veamos un ejemplo:
package com.concretepage;
import java.util.Arrays;
import java.util.Comparator;
import java.util.function.Consumer;
public class ParallelSortWithComparator {
public static void main(String[] args) {
User[] users = User.getUsers();
Comparator<User> ageComparator = Comparator.comparing(User::getAge);
System.out.println("--Sort complete array--");
Arrays.parallelSort(users, ageComparator);
Consumer<User> printUser = u-> System.out.println(u.getName()+"-"+u.getAge());
Arrays.stream(users).forEach(printUser);
System.out.println("--Sort array from index 1 to 4--");
users = User.getUsers();
Arrays.parallelSort(users, 1, 4, ageComparator);
Arrays.stream(users).forEach(printUser);
}
}
domingo, 24 de diciembre de 2017
sábado, 23 de diciembre de 2017
Ukui desktop para Debian, Ubuntu y derivados
¡Útil, conveniente e intuitivo!
UKUI es un entorno de escritorio ligero basado en plugins para Linux y otras distribuciones Unix. Proporciona una experiencia más simple y agradable para navegar, buscar y administrar su equipo. Fue desarrollado utilizando GTK y Qt.
Veamos una imagenes:
Dejo link: http://www.ukui.org/
jueves, 21 de diciembre de 2017
Un resumen de Scala for the Impatient, parte 35
Operadores de asignación.
Los operadores de asignación tienen la forma operador= y se utilizan de la siguiente forma:
a operator= b
que es igual a decir :
a = a operator b
Por ejemplo a+= b es equivalente a escribir a = a + b
Hay unos detalles técnicos :
<=, >= y != no son operadores de asignación
Un operador que comienza con = nunca es un operador de asignación (==, ===, =/=, etc)
Si a tiene un operador llamado operator= entonces este sera llamado directamente.
Precedencia.
Cuando tenemos más de un operador, sin paréntesis debemos definir las precedencias de los operadores. Dado que esto define el orden de resolución, por ejemplo :
1 + 2 * 3
El operador * se evalúa primero y luego la suma, esto fue definido por conversión. Lenguajes como C++ y Java tienen un numero fijo de operadores por lo tanto es más sencillo definir la precedencias (se pueden enumerar). En cambio en Scala tenemos un numero arbitrario de operadores por lo que se debe definir esto de forma general.
Excepto para los operadores de asignación, la precedencia está determinada por el primer carácter del operador.
Precedencia más alta: un carácter de operador que no sea los de abajo
* / %
+ -
:
< >
! =
&
^
|
Un carácter que no es un carácter de operador
Prioridad más baja: operadores de asignación
Los caracteres en la misma fila producen operadores con la misma precedencia. Por ejemplo, + y -> tienen la misma precedencia.
Los operadores de Postfijos tienen una precedencia menor que los operadores de infijo:
a infixOp b postfixOp es igual a escribir : (a infixOp b)postfixOp
Asociatividad
Cuando hay un conjunto de operadores con la misma precedencia entra en juego la asociatividad, es decir si resuelve de derecha a izquierda o izquierda a derecha. En scala todos los operadores son asociativos por la izquierda excepto:
Por ejemplo el operador :: construye una lista por medio de asociatividad por la derecha:
1 :: 2 :: 3 :: Nil
esto significa
1 :: (2 :: (3 :: Nil))
Esto es así porque necesita construir primero la lista 3 :: Nil para que este parámetro sea usado por le expresión 2 :: (3 :: Nil)
La expresión 3 :: Dicha expresión es igual a la expresión Nil.::(3)
Los operadores de asignación tienen la forma operador= y se utilizan de la siguiente forma:
a operator= b
que es igual a decir :
a = a operator b
Por ejemplo a+= b es equivalente a escribir a = a + b
Hay unos detalles técnicos :
<=, >= y != no son operadores de asignación
Un operador que comienza con = nunca es un operador de asignación (==, ===, =/=, etc)
Si a tiene un operador llamado operator= entonces este sera llamado directamente.
Precedencia.
Cuando tenemos más de un operador, sin paréntesis debemos definir las precedencias de los operadores. Dado que esto define el orden de resolución, por ejemplo :
1 + 2 * 3
El operador * se evalúa primero y luego la suma, esto fue definido por conversión. Lenguajes como C++ y Java tienen un numero fijo de operadores por lo tanto es más sencillo definir la precedencias (se pueden enumerar). En cambio en Scala tenemos un numero arbitrario de operadores por lo que se debe definir esto de forma general.
Excepto para los operadores de asignación, la precedencia está determinada por el primer carácter del operador.
Precedencia más alta: un carácter de operador que no sea los de abajo
* / %
+ -
:
< >
! =
&
^
|
Un carácter que no es un carácter de operador
Prioridad más baja: operadores de asignación
Los caracteres en la misma fila producen operadores con la misma precedencia. Por ejemplo, + y -> tienen la misma precedencia.
Los operadores de Postfijos tienen una precedencia menor que los operadores de infijo:
a infixOp b postfixOp es igual a escribir : (a infixOp b)postfixOp
Asociatividad
Cuando hay un conjunto de operadores con la misma precedencia entra en juego la asociatividad, es decir si resuelve de derecha a izquierda o izquierda a derecha. En scala todos los operadores son asociativos por la izquierda excepto:
- Los operadores que terminan en :
- Los operadores de asignación
Por ejemplo el operador :: construye una lista por medio de asociatividad por la derecha:
1 :: 2 :: 3 :: Nil
esto significa
1 :: (2 :: (3 :: Nil))
Esto es así porque necesita construir primero la lista 3 :: Nil para que este parámetro sea usado por le expresión 2 :: (3 :: Nil)
La expresión 3 :: Dicha expresión es igual a la expresión Nil.::(3)
martes, 19 de diciembre de 2017
Un resumen de Scala for the Impatient, parte 34
Si hemos programado en C++ recordaremos que nos permite sobrescribir operadores, pero esto requería una muy pesada definición. Esto es muy diferente en Scala, las definiciones son mucho más fáciles y claras.
Sobrescribir operadores nos da una sintaxis más clara de nuestro código y nos acerca a la notación matemática.
En esta parte veremos como definir operadores binarios y unarios. Pero antes debemos aclarar algunos conceptos.
Identificadores
El nombre de las variables, funciones, clases, etc. se denominan identificadores. En Scala tenes más opciones de nombres para los identificadores que en java. Por supuesto podemos hacerlo igual que java, una letra seguida de letra o dígito. Como Java también permite caracteres unicode, es decir :
es una variable valida.
También se puede utilizar caracteres de operadores en identificadores como :
Por ejemplo
es un identificador valido y se puede hacer:
de esta manera podemos escribir
de forma valida.
Note que las palabras : @ # : = _ => <- <: <% >: fi ̈ son palabras reservadas.
Por lo dicho anteriormente este es una variable valida:
val happy_birthday_!!! = "Bonne anniversaire!!!"
Por ultimo se puede incluir cualquier conjunto de palabras en `` como por ejemplo:
val `val` = 42
Si bien no parece útil, lo es por ejemplo si deseamos llamar a un método java que sea palabra reservada en scala, de esta forma podremos hacerlo.
Operador infijo
Se puede escribir:
a identificador b
Donde identificador es un método con 2 parámetros. Uno implícito y el otro explicito. Por ejemplo:
1 to 10
Que es igual a llamar 1.to(10)
Esto se denomina una expresión infija porque se encuentra entre los 2 parámetros. El operador puede contener letras o no, como el caso de -> :
1 -> 10 es igual a 1.->(10)
Para definir un operador en una clase, solo debe definir un método con el nombre del operador. Por ejemplo la clase Fraction:
class Fraction(n: Int, d: Int) {
private val num = ...
private val den = ...
...
def *(other: Fraction) = new Fraction(num * other.num, den * other.den)
}
Operadores unarios
Los operadores infijos son binarios, es decir necesitan 2 parámetros. Un operador con un parámetro se lo denomina unario.
Los cuatro operadores: -, +, !, ~ se pueden utilizar como operadores prefijos, es decir se puede escribir el operador y luego el parámetro como por ejemplo :
-a es idual a llamar a : a.unary_-
Si es postfijo, en ese caso no hay problema, se puede llamar el método con . o espacio, por ejemplo :
12 toString
es igual a llamar a : 12.toString()
Cuando utilizamos el operador unario postfijo con espacio y sin paréntesis nos puede dar un error de compilación. Dado que no queda expresado que no estamos utilizando parámetros. Veamos un ejemplo:
val result = 42 toString
println(result)
En este caso el compilador interpreta que se esta escribiendo lo siguiente :
val result = 42.toString(println(result))
Por esta razón nos lanzara un error de compilación, que dirá que el método tiene muchos parámetros. Por esta razón el compilador, lanza un warning cuando utilizamos esta notación, esto se puede desactivar con el parámetro del compilador -language:postfixOps o agregando el import :
import scala.language.postfixOps
Sobrescribir operadores nos da una sintaxis más clara de nuestro código y nos acerca a la notación matemática.
En esta parte veremos como definir operadores binarios y unarios. Pero antes debemos aclarar algunos conceptos.
Identificadores
El nombre de las variables, funciones, clases, etc. se denominan identificadores. En Scala tenes más opciones de nombres para los identificadores que en java. Por supuesto podemos hacerlo igual que java, una letra seguida de letra o dígito. Como Java también permite caracteres unicode, es decir :
es una variable valida.
También se puede utilizar caracteres de operadores en identificadores como :
- Caracteres ASCII como ! # % & * + - / : < = > ? @ \ ^ | ~ , dígitos, . , ; marcas de puntuación, guión bajo, paréntesis () [] {} o comillas “ ' `
- Caracteres de símbolos matemáticos
Por ejemplo
es un identificador valido y se puede hacer:
de esta manera podemos escribir
de forma valida.
Note que las palabras : @ # : = _ => <- <: <% >: fi ̈ son palabras reservadas.
Por lo dicho anteriormente este es una variable valida:
val happy_birthday_!!! = "Bonne anniversaire!!!"
Por ultimo se puede incluir cualquier conjunto de palabras en `` como por ejemplo:
val `val` = 42
Si bien no parece útil, lo es por ejemplo si deseamos llamar a un método java que sea palabra reservada en scala, de esta forma podremos hacerlo.
Operador infijo
Se puede escribir:
a identificador b
Donde identificador es un método con 2 parámetros. Uno implícito y el otro explicito. Por ejemplo:
1 to 10
Que es igual a llamar 1.to(10)
Esto se denomina una expresión infija porque se encuentra entre los 2 parámetros. El operador puede contener letras o no, como el caso de -> :
1 -> 10 es igual a 1.->(10)
Para definir un operador en una clase, solo debe definir un método con el nombre del operador. Por ejemplo la clase Fraction:
class Fraction(n: Int, d: Int) {
private val num = ...
private val den = ...
...
def *(other: Fraction) = new Fraction(num * other.num, den * other.den)
}
Operadores unarios
Los operadores infijos son binarios, es decir necesitan 2 parámetros. Un operador con un parámetro se lo denomina unario.
Los cuatro operadores: -, +, !, ~ se pueden utilizar como operadores prefijos, es decir se puede escribir el operador y luego el parámetro como por ejemplo :
-a es idual a llamar a : a.unary_-
Si es postfijo, en ese caso no hay problema, se puede llamar el método con . o espacio, por ejemplo :
12 toString
es igual a llamar a : 12.toString()
Cuando utilizamos el operador unario postfijo con espacio y sin paréntesis nos puede dar un error de compilación. Dado que no queda expresado que no estamos utilizando parámetros. Veamos un ejemplo:
val result = 42 toString
println(result)
En este caso el compilador interpreta que se esta escribiendo lo siguiente :
val result = 42.toString(println(result))
Por esta razón nos lanzara un error de compilación, que dirá que el método tiene muchos parámetros. Por esta razón el compilador, lanza un warning cuando utilizamos esta notación, esto se puede desactivar con el parámetro del compilador -language:postfixOps o agregando el import :
import scala.language.postfixOps
lunes, 18 de diciembre de 2017
Goland, la nueva ide de Jetbrains para Go.
Una empresa que esta haciendo las cosas bien hace tiempo es Jetbrains y ahora ha lanzado una IDE para Go. Si no recuerdan bien Go es el lenguaje de google, que espera remplazar a c.
Como podemos ver Jetbrains suma un IDE a su lista de productos como PyCharm para Python y RubyMine para Ruby.
De GoLands podemos nombrar algunas de las características como:
- Asistente de programación: al analizar el código fuente, proporciona características como la finalización del código, la navegación, la refactorización y el formateo, todos ellos específicos de Go.
- Editor de código: resaltado de sintaxis y sugerencias de parámetros para facilitar la lectura y comprensión del código
- Diseño ergonómico: la interfaz ha sido diseñada de la manera más directa y productiva posible
- Desarrollo de front-end y back-end: soporte de primera clase para lenguajes y frameworks front-end, y herramientas para acceder y consultar bases de datos
- Herramientas integradas: Herramientas comúnmente requeridas como depuradores, integración de control de versiones y corredores de prueba vienen instalados y no necesitan instalarse como complementos
- Ecosistema de plugins: el ecosistema de plugins existente de JetBrains está disponible, abriendo muchas herramientas y características adicionales
- Los desarrolladores que ya están familiarizados con IntelliJ se sentirán a gusto programando en go.
La herramienta de depuración incluida también es similar a las de las suites de herramientas existentes de JetBrains. Los desarrolladores ahora podrán pasar por el código, agregar puntos de interrupción, evaluar expresiones, agregar relojes y más. Esto trae una modernización a aquellos más familiarizados con flujos de trabajo de depuración más débiles.
JetBrains planea expandir y mejorar este conjunto de características de forma regular, siguiendo el ciclo de lanzamiento típico de todas sus herramientas: las actualizaciones de versiones principales se realizarán trimestralmente, y las versiones menores y de parches suceden incluso con mayor frecuencia.
GoLand sigue el modelo estándar de licencia de JetBrains, con una prueba inicial de 30 días seguida de suscripciones mensuales o anuales, disponible tanto para individuos como para empresas. Para los usuarios de IntelliJ ultimate edition, su funcionalidad se puede instalar como un complemento.
Dejo link:
https://www.jetbrains.com/go/
sábado, 16 de diciembre de 2017
Primeros pasos con F#
Si bien hemos hablado de F# en el blog nunca hice un post del lenguaje en si, bueno vamos a cambiar eso.
Si vamos a la pagina de F# nos dira que es un lenguaje open source, multiplataforma y funcional. Capaz de resolver problemas complejos de forma simple.
Por que utilizar o aprender F#?
Aquí hay una descripción general muy rápida sobre cómo leer el código F# para los recién llegados que no estén familiarizados con la sintaxis. La sintaxis F# es muy clara y directa cuando te acostumbras. En muchos sentidos, es más simple que la sintaxis C#, con menos palabras clave y casos especiales.
El siguiente código de ejemplo es un script sencillo de F # que muestra la mayoría de los conceptos que necesita de forma regular.
// single line comments use a double slash
(* multi line comments use (* . . . *) pair -end of multi line comment- *)
// ======== "Variables" (but not really) ==========
// The "let" keyword defines an (immutable) value
let myInt = 5
let myFloat = 3.14
let myString = "hello" //note that no types needed
// ======== Lists ============
let twoToFive = [2;3;4;5] // Square brackets create a list with
// semicolon delimiters.
let oneToFive = 1 :: twoToFive // :: creates list with new 1st element
// The result is [1;2;3;4;5]
let zeroToFive = [0;1] @ twoToFive // @ concats two lists
// IMPORTANT: commas are never used as delimiters, only semicolons!
// ======== Functions ========
// The "let" keyword also defines a named function.
let square x = x * x // Note that no parens are used.
square 3 // Now run the function. Again, no parens.
let add x y = x + y // don't use add (x,y)! It means something
// completely different.
add 2 3 // Now run the function.
// to define a multiline function, just use indents. No semicolons needed.
let evens list =
let isEven x = x%2 = 0 // Define "isEven" as an inner ("nested") function
List.filter isEven list // List.filter is a library function
// with two parameters: a boolean function
// and a list to work on
evens oneToFive // Now run the function
// You can use parens to clarify precedence. In this example,
// do "map" first, with two args, then do "sum" on the result.
// Without the parens, "List.map" would be passed as an arg to List.sum
let sumOfSquaresTo100 =
List.sum ( List.map square [1..100] )
// You can pipe the output of one operation to the next using "|>"
// Here is the same sumOfSquares function written using pipes
let sumOfSquaresTo100piped =
[1..100] |> List.map square |> List.sum // "square" was defined earlier
// you can define lambdas (anonymous functions) using the "fun" keyword
let sumOfSquaresTo100withFun =
[1..100] |> List.map (fun x->x*x) |> List.sum
// In F# returns are implicit -- no "return" needed. A function always
// returns the value of the last expression used.
// ======== Pattern Matching ========
// Match..with.. is a supercharged case/switch statement.
let simplePatternMatch =
let x = "a"
match x with
| "a" -> printfn "x is a"
| "b" -> printfn "x is b"
| _ -> printfn "x is something else" // underscore matches anything
// Some(..) and None are roughly analogous to Nullable wrappers
let validValue = Some(99)
let invalidValue = None
// In this example, match..with matches the "Some" and the "None",
// and also unpacks the value in the "Some" at the same time.
let optionPatternMatch input =
match input with
| Some i -> printfn "input is an int=%d" i
| None -> printfn "input is missing"
optionPatternMatch validValue
optionPatternMatch invalidValue
// ========= Complex Data Types =========
// Tuple types are pairs, triples, etc. Tuples use commas.
let twoTuple = 1,2
let threeTuple = "a",2,true
// Record types have named fields. Semicolons are separators.
type Person = {First:string; Last:string}
let person1 = {First="john"; Last="Doe"}
// Union types have choices. Vertical bars are separators.
type Temp =
| DegreesC of float
| DegreesF of float
let temp = DegreesF 98.6
// Types can be combined recursively in complex ways.
// E.g. here is a union type that contains a list of the same type:
type Employee =
| Worker of Person
| Manager of Employee list
let jdoe = {First="John";Last="Doe"}
let worker = Worker jdoe
// ========= Printing =========
// The printf/printfn functions are similar to the
// Console.Write/WriteLine functions in C#.
printfn "Printing an int %i, a float %f, a bool %b" 1 2.0 true
printfn "A string %s, and something generic %A" "hello" [1;2;3;4]
// all complex types have pretty printing built in
printfn "twoTuple=%A,\nPerson=%A,\nTemp=%A,\nEmployee=%A"
twoTuple person1 temp worker
// There are also sprintf/sprintfn functions for formatting data
// into a string, similar to String.Format.
Si vamos a la pagina de F# nos dira que es un lenguaje open source, multiplataforma y funcional. Capaz de resolver problemas complejos de forma simple.
Por que utilizar o aprender F#?
- Concisión. F # no está lleno de "ruido" de codificación, como llaves, punto y coma, etc. Casi nunca tiene que especificar el tipo de un objeto, gracias a un potente sistema de inferencia de tipo. Y generalmente requiere menos líneas de código para resolver el mismo problema.
- Conveniente. Muchas tareas de programación comunes son mucho más simples en F#. Esto incluye cosas como crear y usar definiciones de tipos complejos, hacer el procesamiento de listas, comparación e igualdad, máquinas de estado y mucho más. Y debido a que las funciones son objetos de primera clase, es muy fácil crear código poderoso y reutilizable creando funciones que tienen otras funciones como parámetros, o que combinan funciones existentes para crear nuevas funcionalidades.
- Exactitud. F# tiene un sistema de tipo muy poderoso que evita muchos errores comunes, como las excepciones de referencia nula. Además, a menudo puede codificar la lógica de negocios utilizando el sistema de tipo en sí, de modo que es realmente imposible escribir código incorrecto, porque se detecta en tiempo de compilación como un error de tipo.
- Concurrencia: F# tiene una serie de herramientas y bibliotecas integradas para ayudar con los sistemas de programación cuando ocurre más de una cosa a la vez. La programación asincrónica es directamente compatible, como lo es el paralelismo. F# también tiene un sistema de cola de mensajes y un excelente soporte para el manejo de eventos y programación reactiva. Y debido a que las estructuras de datos son inmutables por defecto, compartir estado y evitar bloqueos es mucho más fácil.
- Completo. Aunque F # es un lenguaje funcional de corazón, admite otros estilos que no son 100% puros, lo que facilita mucho la interacción con el mundo no puro de sitios web, bases de datos, otras aplicaciones, etc. En particular, F# está diseñado como un lenguaje híbrido funcional / OO, por lo que puede hacer casi todo lo que C# puede hacer también. Por supuesto, F# se integra sin problemas con el ecosistema .NET, que le da acceso a todas las herramientas y bibliotecas .NET de terceros. Finalmente, es parte de Visual Studio, lo que significa que obtiene un buen editor con soporte IntelliSense, un depurador y muchos complementos para pruebas unitarias, control de código fuente y otras tareas de desarrollo.
Aquí hay una descripción general muy rápida sobre cómo leer el código F# para los recién llegados que no estén familiarizados con la sintaxis. La sintaxis F# es muy clara y directa cuando te acostumbras. En muchos sentidos, es más simple que la sintaxis C#, con menos palabras clave y casos especiales.
El siguiente código de ejemplo es un script sencillo de F # que muestra la mayoría de los conceptos que necesita de forma regular.
// single line comments use a double slash
(* multi line comments use (* . . . *) pair -end of multi line comment- *)
// ======== "Variables" (but not really) ==========
// The "let" keyword defines an (immutable) value
let myInt = 5
let myFloat = 3.14
let myString = "hello" //note that no types needed
// ======== Lists ============
let twoToFive = [2;3;4;5] // Square brackets create a list with
// semicolon delimiters.
let oneToFive = 1 :: twoToFive // :: creates list with new 1st element
// The result is [1;2;3;4;5]
let zeroToFive = [0;1] @ twoToFive // @ concats two lists
// IMPORTANT: commas are never used as delimiters, only semicolons!
// ======== Functions ========
// The "let" keyword also defines a named function.
let square x = x * x // Note that no parens are used.
square 3 // Now run the function. Again, no parens.
let add x y = x + y // don't use add (x,y)! It means something
// completely different.
add 2 3 // Now run the function.
// to define a multiline function, just use indents. No semicolons needed.
let evens list =
let isEven x = x%2 = 0 // Define "isEven" as an inner ("nested") function
List.filter isEven list // List.filter is a library function
// with two parameters: a boolean function
// and a list to work on
evens oneToFive // Now run the function
// You can use parens to clarify precedence. In this example,
// do "map" first, with two args, then do "sum" on the result.
// Without the parens, "List.map" would be passed as an arg to List.sum
let sumOfSquaresTo100 =
List.sum ( List.map square [1..100] )
// You can pipe the output of one operation to the next using "|>"
// Here is the same sumOfSquares function written using pipes
let sumOfSquaresTo100piped =
[1..100] |> List.map square |> List.sum // "square" was defined earlier
// you can define lambdas (anonymous functions) using the "fun" keyword
let sumOfSquaresTo100withFun =
[1..100] |> List.map (fun x->x*x) |> List.sum
// In F# returns are implicit -- no "return" needed. A function always
// returns the value of the last expression used.
// ======== Pattern Matching ========
// Match..with.. is a supercharged case/switch statement.
let simplePatternMatch =
let x = "a"
match x with
| "a" -> printfn "x is a"
| "b" -> printfn "x is b"
| _ -> printfn "x is something else" // underscore matches anything
// Some(..) and None are roughly analogous to Nullable wrappers
let validValue = Some(99)
let invalidValue = None
// In this example, match..with matches the "Some" and the "None",
// and also unpacks the value in the "Some" at the same time.
let optionPatternMatch input =
match input with
| Some i -> printfn "input is an int=%d" i
| None -> printfn "input is missing"
optionPatternMatch validValue
optionPatternMatch invalidValue
// ========= Complex Data Types =========
// Tuple types are pairs, triples, etc. Tuples use commas.
let twoTuple = 1,2
let threeTuple = "a",2,true
// Record types have named fields. Semicolons are separators.
type Person = {First:string; Last:string}
let person1 = {First="john"; Last="Doe"}
// Union types have choices. Vertical bars are separators.
type Temp =
| DegreesC of float
| DegreesF of float
let temp = DegreesF 98.6
// Types can be combined recursively in complex ways.
// E.g. here is a union type that contains a list of the same type:
type Employee =
| Worker of Person
| Manager of Employee list
let jdoe = {First="John";Last="Doe"}
let worker = Worker jdoe
// ========= Printing =========
// The printf/printfn functions are similar to the
// Console.Write/WriteLine functions in C#.
printfn "Printing an int %i, a float %f, a bool %b" 1 2.0 true
printfn "A string %s, and something generic %A" "hello" [1;2;3;4]
// all complex types have pretty printing built in
printfn "twoTuple=%A,\nPerson=%A,\nTemp=%A,\nEmployee=%A"
twoTuple person1 temp worker
// There are also sprintf/sprintfn functions for formatting data
// into a string, similar to String.Format.
Dejo link:
miércoles, 13 de diciembre de 2017
Entrando en .NET Core con the Windows Compatibility Pack
Una de las mayores diferencias entre .net y .net core es que este ultimo corre en Linux. Pero para aplicaciones de grandes empresas, realizar una migración en un solo paso no es factible. Por este motivo, Microsoft recomienda una transición incremental:
Migrar a ASP.NET Core
Migrar a .NET Core
Migrar a Linux
Y luego Migrar a Azure (host en linux)
Si bien eso suena bien en teoría, si falta una API crítica los proyectos no llegarán ni al paso 2. En este caso es donde entra en juego he Windows Compatibility Pack para .NET Core. Abarcando 20,000 APIs, esta colección de paquetes .net tiene como objetivo abordar las necesidades de la librerías para los desarrolladores de aplicaciones web.
Las API recientemente portadas se dividen aproximadamente en dos categorías: solo Windows y multiplataforma. Las API solo de Windows incluyen:
- Active directory
- Criptografia
- Registros de eventos y contadores de rendimiento
- File system security
- Named pipes
- Registry Access
- Windows Services
En su mayor parte, están relacionados con el sistema operativo Windows, y los equivalentes de Linux a menudo tienen un diseño diferente.
Las bibliotecas multiplataforma incluyen:
- Caching
- ConfigurationManager
- DatasetExtensions (usado para acceso a base de datos sin un ORM)
- ODBC database access
- System.Configuration.ConfigurationManager (MEF v1)
- System.Drawing
- System.IO.Packaging
- System.ServiceModel (i.e. WCF)
Cabe señalar que estas API se están omitiendo intencionalmente de la distribución .NET Core completa.
Suscribirse a:
Entradas (Atom)