Translate
domingo, 27 de agosto de 2017
Empezando con Elixir 6
Funciones
En Elixir y muchos lenguajes funcionales, las funciones son ciudadanos de primera clase.
Funciones Anónimas
Tal como su nombre lo indica, una función anónima no tiene nombre. Como vimos en la lección de Enum, éstos se pasan con frecuencia a otras funciones. Para definir una función anónima en Elixir necesitamos las palabras clave fn y end. Dentro de éstos podemos definir cualquier número de parámetros y cuerpos funcionales separados por ->
iex> sum = fn (a, b) -> a + b end
iex> sum.(2, 3)
5
El operador &
El uso de funciones anónimas es una práctica común en Elixir hay una forma abreviada de hacerlo:
iex> sum = &(&1 + &2)
iex> sum.(2, 3)
5
Como probablemente ya se supone, en la versión abreviada nuestros parámetros están disponibles para nosotros como & 1, & 2, & 3, y así sucesivamente.
Pattern Matching
Pattern matching no esta limitado solo a variables sino que tambien se pueden utilizar en funciones.
Se pueden utilizar pattern matching con el primer conjunto de parámetros que coinciden e invoca el cuerpo correspondiente:
iex> handle_result = fn
...> {:ok, result} -> IO.puts "Handling result..."
...> {:error} -> IO.puts "An error has occurred!"
...> end
iex> some_result = 1
iex> handle_result.({:ok, some_result})
Handling result...
iex> handle_result.({:error})
An error has occurred!
Funciones con nombre
Podemos definir funciones con nombre utilizando la palabra clave def. Las funciones definidas dentro de un modulo pueden ser accedidas por otros módulos:
defmodule Greeter do
def hello(name) do
"Hello, " <> name
end
end
iex> Greeter.hello("Sean")
"Hello, Sean"
Si queremos definir una función en una linea podemos usar do:
defmodule Greeter do
def hello(name), do: "Hello, " <> name
end
Y podemos utilizar pattern matching:
defmodule Length do
def of([]), do: 0
def of([_ | tail]), do: 1 + of(tail)
end
iex> Length.of []
0
iex> Length.of [1, 2, 3]
3
Funciones con nombre y número de argumentos
Como el lenguaje es de tipado débil, la firma de la función esta dada por el nombre de la función y la cantidad de parámetros. Es decir las funciones aceptan sobre carga y esta dada por el numero de parametros:
defmodule Greeter2 do
def hello(), do: "Hello, anonymous person!" # hello/0
def hello(name), do: "Hello, " <> name # hello/1
def hello(name1, name2), do: "Hello, #{name1} and #{name2}"
# hello/2
end
A diferencia de otros lenguajes, la firma de una función esta dada por el nombre y el numero de parámetros.
Funciones privadas
Una función privada solo se puede llamar dentro del modulo y se define con defp :
defmodule Greeter do
def hello(name), do: phrase <> name
defp phrase, do: "Hello, "
end
iex> Greeter.hello("Sean")
"Hello, Sean"
iex> Greeter.phrase
** (UndefinedFunctionError) undefined function: Greeter.phrase/0
Greeter.phrase()
Guards
En el ejemplo siguiente tenemos dos funciones con la misma firma, nos basamos en guards para determinar qué utilizar en función del tipo del argumento:
defmodule Greeter do
def hello(names) when is_list(names) do
names
|> Enum.join(", ")
|> hello
end
def hello(name) when is_binary(name) do
phrase() <> name
end
defp phrase, do: "Hello, "
end
iex> Greeter.hello ["Sean", "Steve"]
"Hello, Sean, Steve"
Argumentos por defecto
Se pueden utilizar argumentos por defecto:
defmodule Greeter do
def hello(name, language_code \\ "en") do
phrase(language_code) <> name
end
defp phrase("en"), do: "Hello, "
defp phrase("es"), do: "Hola, "
end
iex> Greeter.hello("Sean", "en")
"Hello, Sean"
iex> Greeter.hello("Sean")
"Hello, Sean"
iex> Greeter.hello("Sean", "es")
"Hola, Sean"
Cuando combinamos nuestro ejemplo de guard con argumentos predeterminados, nos topamos con un problema. Veamos cómo podría verse:
defmodule Greeter do
def hello(names, language_code \\ "en") when is_list(names) do
names
|> Enum.join(", ")
|> hello(language_code)
end
def hello(name, language_code \\ "en") when is_binary(name) do
phrase(language_code) <> name
end
defp phrase("en"), do: "Hello, "
defp phrase("es"), do: "Hola, "
end
** (CompileError) def hello/2 has default values and multiple clauses, define a function head with the defaults
Elixir no le gusta los argumentos por defecto en múltiples funciones de coincidencia, puede ser confuso. Para manejar esto agregamos una cabeza de función con nuestros argumentos por defecto:
defmodule Greeter do
def hello(names, language_code \\ "en")
def hello(names, language_code) when is_list(names) do
names
|> Enum.join(", ")
|> hello(language_code)
end
def hello(name, language_code) when is_binary(name) do
phrase(language_code) <> name
end
defp phrase("en"), do: "Hello, "
defp phrase("es"), do: "Hola, "
end
iex> Greeter.hello ["Sean", "Steve"]
"Hello, Sean, Steve"
iex> Greeter.hello ["Sean", "Steve"], "es"
"Hola, Sean, Steve"
Dejo link: https://elixirschool.com/en/lessons/basics/functions/
miércoles, 23 de agosto de 2017
Datacamp, aprendiendo a manipular datos
Data + camp, es decir un campamento para datos, es realidad no, datacamp es un sitio donde podemos hacer toda clase de cursos relacionados al procesamiento de datos.
Se pueden hacer toda clase de cursos de manipulación de datos pero se usa sobre todo Python y R. También hay uno sobre Apache spark
Sin más que lo disfruten!!
Dejo link: https://www.datacamp.com/
Comienza la inscripción de los cursos Gugler
Quiero invitarlos a los cursos gugler, que se dictan de forma remota o a distancia o presencial, para mayor información:
Dejo link: https://inscripciones.gugler.com.ar
martes, 22 de agosto de 2017
Ceylon es de la fundación eclipse
Al parecer el lenguaje Ceylon se ha movido a la fundación eclipse. Por medio de un post lo han publicado Stéphane Épardaud y Gavin King, nos han dicho:
"Red Hat es sinónimo de Open source, calidad y confianza a la comunidad. Pero también hemos tenido un temor creciente de que la fuerte asociación con una sola compañía pueda haber frenado nuestra comunidad. Siempre hemos visto este proyecto como un "terreno neutral", no como un vehículo para los objetivos de negocio de una empresa, pero no estamos seguros si el proyecto es percibido de esa manera desde fuera."
Por lo tanto este proyecto va estar bajo la fundación eclipse. Esto no se si es bueno o malo, en lo que coincido es que le va dar una briza más open sources al proyecto y espero que siga creciendo.
Dejo links:
https://ceylon-lang.org/blog/2017/08/21/eclipse-ceylon/
https://projects.eclipse.org/proposals/eclipse-ceylon
"Red Hat es sinónimo de Open source, calidad y confianza a la comunidad. Pero también hemos tenido un temor creciente de que la fuerte asociación con una sola compañía pueda haber frenado nuestra comunidad. Siempre hemos visto este proyecto como un "terreno neutral", no como un vehículo para los objetivos de negocio de una empresa, pero no estamos seguros si el proyecto es percibido de esa manera desde fuera."
Por lo tanto este proyecto va estar bajo la fundación eclipse. Esto no se si es bueno o malo, en lo que coincido es que le va dar una briza más open sources al proyecto y espero que siga creciendo.
Dejo links:
https://ceylon-lang.org/blog/2017/08/21/eclipse-ceylon/
https://projects.eclipse.org/proposals/eclipse-ceylon
sábado, 19 de agosto de 2017
Como va el resumen de Scala for the Impatient? 2
Siguiendo con el post "Como va el resumen de Scala for the Impatient?"
Puff vamos a un ritmo sostenido...
Dejo los links:
http://emanuelpeg.blogspot.com.ar/2017/03/un-resumen-de-scala-for-impatient-parte_26.html
http://emanuelpeg.blogspot.com.ar/2017/04/un-resumen-de-scala-for-impatient-parte.html
http://emanuelpeg.blogspot.com.ar/2017/04/un-resumen-de-scala-for-impatient-parte_15.html
http://emanuelpeg.blogspot.com.ar/2017/04/un-resumen-de-scala-for-impatient-parte_30.html
http://emanuelpeg.blogspot.com.ar/2017/05/un-resumen-de-scala-for-impatient-parte.html
http://emanuelpeg.blogspot.com.ar/2017/05/un-resumen-de-scala-for-impatient-parte_28.html
http://emanuelpeg.blogspot.com.ar/2017/06/un-resumen-de-scala-for-impatient-parte.html
http://emanuelpeg.blogspot.com.ar/2017/06/un-resumen-de-scala-for-impatient-parte_20.html
http://emanuelpeg.blogspot.com.ar/2017/06/un-resumen-de-scala-for-impatient-parte_61.html
http://emanuelpeg.blogspot.com.ar/2017/06/un-resumen-de-scala-for-impatient-parte_25.html
http://emanuelpeg.blogspot.com.ar/2017/07/un-resumen-de-scala-for-impatient-parte.html
http://emanuelpeg.blogspot.com.ar/2017/07/un-resumen-de-scala-for-impatient-parte_24.html
http://emanuelpeg.blogspot.com.ar/2017/08/un-resumen-de-scala-for-impatient-parte.html
http://emanuelpeg.blogspot.com.ar/2017/08/un-resumen-de-scala-for-impatient-parte_6.html
http://emanuelpeg.blogspot.com.ar/2017/08/un-resumen-de-scala-for-impatient-parte_31.html
http://emanuelpeg.blogspot.com.ar/2017/08/un-resumen-de-scala-for-impatient-parte_13.html
http://emanuelpeg.blogspot.com.ar/2017/08/un-resumen-de-scala-for-impatient-parte_19.html
Puff vamos a un ritmo sostenido...
Dejo los links:
http://emanuelpeg.blogspot.com.ar/2017/03/un-resumen-de-scala-for-impatient-parte_26.html
http://emanuelpeg.blogspot.com.ar/2017/04/un-resumen-de-scala-for-impatient-parte.html
http://emanuelpeg.blogspot.com.ar/2017/04/un-resumen-de-scala-for-impatient-parte_15.html
http://emanuelpeg.blogspot.com.ar/2017/04/un-resumen-de-scala-for-impatient-parte_30.html
http://emanuelpeg.blogspot.com.ar/2017/05/un-resumen-de-scala-for-impatient-parte.html
http://emanuelpeg.blogspot.com.ar/2017/05/un-resumen-de-scala-for-impatient-parte_28.html
http://emanuelpeg.blogspot.com.ar/2017/06/un-resumen-de-scala-for-impatient-parte.html
http://emanuelpeg.blogspot.com.ar/2017/06/un-resumen-de-scala-for-impatient-parte_20.html
http://emanuelpeg.blogspot.com.ar/2017/06/un-resumen-de-scala-for-impatient-parte_61.html
http://emanuelpeg.blogspot.com.ar/2017/06/un-resumen-de-scala-for-impatient-parte_25.html
http://emanuelpeg.blogspot.com.ar/2017/07/un-resumen-de-scala-for-impatient-parte.html
http://emanuelpeg.blogspot.com.ar/2017/07/un-resumen-de-scala-for-impatient-parte_24.html
http://emanuelpeg.blogspot.com.ar/2017/08/un-resumen-de-scala-for-impatient-parte.html
http://emanuelpeg.blogspot.com.ar/2017/08/un-resumen-de-scala-for-impatient-parte_6.html
http://emanuelpeg.blogspot.com.ar/2017/08/un-resumen-de-scala-for-impatient-parte_31.html
http://emanuelpeg.blogspot.com.ar/2017/08/un-resumen-de-scala-for-impatient-parte_13.html
http://emanuelpeg.blogspot.com.ar/2017/08/un-resumen-de-scala-for-impatient-parte_19.html
Un resumen de Scala for the Impatient, parte 30
Traits con implementaciones concretas.
En scala, los métodos de los Trais pueden tener implementaciones. Por ejemplo:
trait ConsoleLogger {
def log(msg: String) { println(msg) }
}
ConsoleLogger provee una implementación, en este caso imprime el log en consola.
Si deseamos utilizar este trait:
class SavingsAccount extends Account with ConsoleLogger {
def withdraw(amount: Double) {
if (amount > balance) log("Insufficient funds")
else balance -= amount
}
…
}
Como se puede ver SavingsAccount es una clase concreta y utiliza el método por defecto de ConsoleLogger. En Java 8, también se puede realizar esto dado que se agregaron los métodos por defecto en las interfaces. Pero en scala una interfaz puede tener estado cosa que no se puede hacer en java.
En scala (y también en otros lenguajes que permiten esto) decimos que la función de ConsoleLog es “mixed in” con la clase SavingsAccount.
Objetos con Trait
Se puede agregar un Trait con una implementación determinada a un objeto cuando se lo instancia. Veamos un ejemplo:
abstract class SavingsAccount extends Account with Logger {
def withdraw(amount: Double) {
if (amount > balance) log("Insufficient funds")
else …
}
...
}
Esta clase es abstracta no tiene implementación para el método log por lo tanto o no podríamos instanciarla o (en java por ejemplo) podemos implementar esto en una clase anónima pero en scala tenemos otra opción podemos agregar una interfaz que implemente este método con la palabra with :
val acct = new SavingsAccount with ConsoleLogger
Por supuesto podemos llamar a otra instancia con diferente traits:
val acct2 = new SavingsAccount with FileLogger
Traits en capas
Puede agregar, a una clase o a un objeto, múltiples rasgos que se invocan entre sí a partir de la última llamada. Esto es útil cuando se necesita transformar un valor en etapas.
Por ejemplo:
trait TimestampLogger extends ConsoleLogger {
override def log(msg: String) {
super.log(s"${java.time.Instant.now()} $msg")
}
}
Supongamos que queremos acotar el mensaje:
trait ShortLogger extends ConsoleLogger {
override def log(msg: String) {
super.log(if (msg.length <= 15) msg else s"${msg.substring(0, 12)}...")
}
}
Como puede ver cada método log es modificado en las traits . La expresión super.log no tiene el mismo significado que en las clases. En los traits la expresión super.log no llama al método del padre sino que importa el orden con que se han agregado. Veamos 2 ejemplos:
val acct1 = new SavingsAccount with TimestampLogger with ShortLogger
val acct2 = new SavingsAccount with ShortLogger with TimestampLogger
Si utilizamos acct1 el log sera:
Sun Feb 06 17:45:45 ICT 2011 Insufficient...
Como podemos ver primero recorta el texto y luego agrega la fecha y si utilizamos acct2 :
Sun Feb 06 1...
Si utilizamos acct2 primero agrega la fecha y luego recorta el texto, con lo que no nos imprime ni siquiera la fecha completa.
Note que se puede indicar con super[ConsoleLog].log(...) de que padre vamos a llamar a este método.
En scala, los métodos de los Trais pueden tener implementaciones. Por ejemplo:
trait ConsoleLogger {
def log(msg: String) { println(msg) }
}
ConsoleLogger provee una implementación, en este caso imprime el log en consola.
Si deseamos utilizar este trait:
class SavingsAccount extends Account with ConsoleLogger {
def withdraw(amount: Double) {
if (amount > balance) log("Insufficient funds")
else balance -= amount
}
…
}
Como se puede ver SavingsAccount es una clase concreta y utiliza el método por defecto de ConsoleLogger. En Java 8, también se puede realizar esto dado que se agregaron los métodos por defecto en las interfaces. Pero en scala una interfaz puede tener estado cosa que no se puede hacer en java.
En scala (y también en otros lenguajes que permiten esto) decimos que la función de ConsoleLog es “mixed in” con la clase SavingsAccount.
Objetos con Trait
Se puede agregar un Trait con una implementación determinada a un objeto cuando se lo instancia. Veamos un ejemplo:
abstract class SavingsAccount extends Account with Logger {
def withdraw(amount: Double) {
if (amount > balance) log("Insufficient funds")
else …
}
...
}
Esta clase es abstracta no tiene implementación para el método log por lo tanto o no podríamos instanciarla o (en java por ejemplo) podemos implementar esto en una clase anónima pero en scala tenemos otra opción podemos agregar una interfaz que implemente este método con la palabra with :
val acct = new SavingsAccount with ConsoleLogger
Por supuesto podemos llamar a otra instancia con diferente traits:
val acct2 = new SavingsAccount with FileLogger
Traits en capas
Puede agregar, a una clase o a un objeto, múltiples rasgos que se invocan entre sí a partir de la última llamada. Esto es útil cuando se necesita transformar un valor en etapas.
Por ejemplo:
trait TimestampLogger extends ConsoleLogger {
override def log(msg: String) {
super.log(s"${java.time.Instant.now()} $msg")
}
}
Supongamos que queremos acotar el mensaje:
trait ShortLogger extends ConsoleLogger {
override def log(msg: String) {
super.log(if (msg.length <= 15) msg else s"${msg.substring(0, 12)}...")
}
}
Como puede ver cada método log es modificado en las traits . La expresión super.log no tiene el mismo significado que en las clases. En los traits la expresión super.log no llama al método del padre sino que importa el orden con que se han agregado. Veamos 2 ejemplos:
val acct1 = new SavingsAccount with TimestampLogger with ShortLogger
val acct2 = new SavingsAccount with ShortLogger with TimestampLogger
Si utilizamos acct1 el log sera:
Sun Feb 06 17:45:45 ICT 2011 Insufficient...
Como podemos ver primero recorta el texto y luego agrega la fecha y si utilizamos acct2 :
Sun Feb 06 1...
Si utilizamos acct2 primero agrega la fecha y luego recorta el texto, con lo que no nos imprime ni siquiera la fecha completa.
Note que se puede indicar con super[ConsoleLog].log(...) de que padre vamos a llamar a este método.
viernes, 18 de agosto de 2017
Java EE bajo una organización open source??
Bueno, yo pensé que Java EE de Oracle iba a ser totalmente de Oracle pero me equivoque...
Al parecer Oracle no le puede sacar dinero a Java EE y por lo tanto quiere donarlo, jeje... Digo yo.
Según lo que han publicado en el blog de la empresa, se quiere que el proceso sea más ágil y responsivo. Por lo tanto se sugiere que sea parte de un fundación open source.
Para dar un resumen concreto, luego de el desarrollo de Java EE 8, vendrá un licenciamiento más flexible y si la papa quema que la agarre el que quiera.
Dejo link: http://www.zdnet.com/article/oracle-considers-moving-java-ee-to-an-open-source-foundation/
miércoles, 16 de agosto de 2017
OpenRA
Quiero recomendarles el Juego OpenRA que es como el Red Alert pero totalmente open source y gratuito. Esta muy bueno!! Es como viajar en el tiempo!!
Dejo link: http://www.openra.net/
domingo, 13 de agosto de 2017
Un resumen de Scala for the Impatient, parte 29
En este capitulo vamos a ver como se trabaja con traits. Los traits
son similares a las interfaces de java solo que estas puede proveer
estados y comportamiento, lo que las hace más útiles.
Una clase puede implementar muchos traits
Un traits puede requerir implementar campos, métodos o súper clases
A diferencia de Java, los traits pueden implementar métodos o
campos.
Cuando se superponen varios traits, el orden es importante: el trait
cuyos métodos se ejecutan primero van en la parte posterior.
Por que no herencia múltiple?
Scala al igual que Java no permite que una clase herede de varias
clases, esto al parecer es una restricción muy grande. Porque no
debemos extender de múltiples clases. Si por ejemplo lenguajes como
C++ lo permiten.
La herencia múltiple trabaja muy bien cuando se combinan clases que
no tienen nada en común, pero cuando combinamos clases que tienen
métodos en común se presentan diferentes problemas.
Veamos un ejemplo un asistente del profesor o alumno auxiliar :
class Student {
def id: String = …
…
}
class Employee {
def id: String = …
...
}
class TeachingAssistant extends Student, Employee { // Ojo que esto
no compila en scala
…
}
Desafortunadamente TeachingAssistant tiene 2 métodos id, por lo
tanto que debe hacer cuando llamamos a myTA.id, siendo myTA una
instancia de TeachingAssistant. (en c++ necesitamos redefinir este
método para clarificar la situación)
Ahora supongamos que tanto el empleado como el estudiante heredan de
persona:
class Person {
var name: String = _
}
class Student extends Person { ... }
class Employee extends Person { ... }
Esto se denomina el problema del diamante, ahora TeachingAssistant
tiene 2 campos nombre pero nosotros solo queremos uno, como se
debería combinar?
En Java se decidió un camino más restrictivo para resolver estos
problemas, no se permite herencia múltiple de clases pero se invento
el concepto de interfaz que no permite que se implementen métodos y
no puede contener atributos pero puede ser heredado de forma
múltiple.
Scala no permite herencia múltiple pero tiene los traits o rasgos.
Un trait puede contener métodos abstractos o concretos y estados y
una clase puede implementar múltiples traits. Ahora veremos como
scala resuelve los conflictos de implementación.
Traits como interfaces Java
Los traits puede ser utilizadas de igual manera que las interfaces de
Java:
trait Logger {
def log(msg: String) // Método abstracto
}
No es necesario indicar que este método es abstracto, si no se
implementa en un trait es automáticamente abstracto.
Y una clase puede proveer una implementación:
class ConsoleLogger extends Logger { // Se usa extends y no
implements
def log(msg: String) { println(msg) } // No es necesario el
override
}
No es necesario agregar override cuando se sobrescribir un método
abstracto de un trait.
Si es necesario agregar más interfaces, se debe hacerlo con la
palabra clave with :
class ConsoleLogger extends Logger with Cloneable with Serializable
Como se puede ver se están utilizando interfaces Cloneable y
Serializable que son de Java, sin ningún problema.
martes, 8 de agosto de 2017
Nuevo centro de contenido de MongoDB
Me llego el siguiente mail, y quería compartirlo con ustedes:
| ||||||||||||
MongoDB Inc., 2017. Todos los derechos reservados. Palacio de Miraflores, Suite 219 & 220, Carrera de San Jerónimo 15 - 2, Madrid 28014, Spain Para darse de baja de futuros mensajes de MongoDB o para actualizar sus preferencias de correo electrónico haga clic aquí. | |||||
domingo, 6 de agosto de 2017
Un resumen de Scala for the Impatient, parte 28
Expresiones Regulares
Cuando tomamos un texto como entrada podemos utilizar expresiones regulares para analizarlos. La clase scala.util.matching.Regex nos puede facilitar las cosas, para construir este objeto, se puede utilizar el método r de la clase String:
val numPattern = "[0-9]+".r
Si la expresión regular contiene barras invertidas o comillas, entonces es una buena idea usar la sintaxis de cadena "raw", "" "..." "". Por ejemplo:
val wsnumwsPattern = """\s+[0-9]+\s+""".r
// A bit easier to read than "\\s+[0-9]+\\s+".r
El metodo findAllIn retorna un iterador que itera por todas las coincidencias. Y esto se puede utilizar en un for :
for (matchString <- numPattern.findAllIn("99 bottles, 98 bottles"))
process matchString
O podemos retornar un arreglo con toArray :
val matches = numPattern.findAllIn("99 bottles, 98 bottles").toArray
// Array(99, 98)
Si buscamos solo el primer elemento que coincida, podemos utilizar el método findFirstIn. Que retorna un Option[String]
val m1 = wsnumwsPattern.findFirstIn("99 bottles, 98 bottles")
// Some(" 98 ")
Para comprobar si el principio de una cadena coincide, utilice findPrefixOf:
numPattern.findPrefixOf("99 bottles, 98 bottles")
// Some(99)
wsnumwsPattern.findPrefixOf("99 bottles, 98 bottles")
// None
Si se desea remplazar la primera coincidencia o todas las coincidencias:
numPattern.replaceFirstIn("99 bottles, 98 bottles", "XX")
// "XX bottles, 98 bottles"
numPattern.replaceAllIn("99 bottles, 98 bottles", "XX")
// "XX bottles, XX bottles"
Grupos de expresiones regulares.
Los grupos son útiles para obtener subexpresiones de expresiones regulares. Añada paréntesis alrededor de las subexpresiones que desea extraer, por ejemplo:
val numitemPattern = "([0-9]+) ([a-z]+)".r
Para hacer coincidir los grupos, utilice el objeto de expresión regular como un "extractor":
val numitemPattern(num, item) = "99 bottles"
// Sets num to "99", item to "bottles"
Si desea extraer grupos de coincidencias múltiples, utilice una instrucción for de este modo:
for (numitemPattern(num, item) <- numitemPattern.findAllIn("99 bottles, 98 bottles"))
process num and item
Cuando tomamos un texto como entrada podemos utilizar expresiones regulares para analizarlos. La clase scala.util.matching.Regex nos puede facilitar las cosas, para construir este objeto, se puede utilizar el método r de la clase String:
val numPattern = "[0-9]+".r
Si la expresión regular contiene barras invertidas o comillas, entonces es una buena idea usar la sintaxis de cadena "raw", "" "..." "". Por ejemplo:
val wsnumwsPattern = """\s+[0-9]+\s+""".r
// A bit easier to read than "\\s+[0-9]+\\s+".r
El metodo findAllIn retorna un iterador que itera por todas las coincidencias. Y esto se puede utilizar en un for :
for (matchString <- numPattern.findAllIn("99 bottles, 98 bottles"))
process matchString
O podemos retornar un arreglo con toArray :
val matches = numPattern.findAllIn("99 bottles, 98 bottles").toArray
// Array(99, 98)
Si buscamos solo el primer elemento que coincida, podemos utilizar el método findFirstIn. Que retorna un Option[String]
val m1 = wsnumwsPattern.findFirstIn("99 bottles, 98 bottles")
// Some(" 98 ")
Para comprobar si el principio de una cadena coincide, utilice findPrefixOf:
numPattern.findPrefixOf("99 bottles, 98 bottles")
// Some(99)
wsnumwsPattern.findPrefixOf("99 bottles, 98 bottles")
// None
Si se desea remplazar la primera coincidencia o todas las coincidencias:
numPattern.replaceFirstIn("99 bottles, 98 bottles", "XX")
// "XX bottles, 98 bottles"
numPattern.replaceAllIn("99 bottles, 98 bottles", "XX")
// "XX bottles, XX bottles"
Grupos de expresiones regulares.
Los grupos son útiles para obtener subexpresiones de expresiones regulares. Añada paréntesis alrededor de las subexpresiones que desea extraer, por ejemplo:
val numitemPattern = "([0-9]+) ([a-z]+)".r
Para hacer coincidir los grupos, utilice el objeto de expresión regular como un "extractor":
val numitemPattern(num, item) = "99 bottles"
// Sets num to "99", item to "bottles"
Si desea extraer grupos de coincidencias múltiples, utilice una instrucción for de este modo:
for (numitemPattern(num, item) <- numitemPattern.findAllIn("99 bottles, 98 bottles"))
process num and item
Un resumen de Scala for the Impatient, parte 27
Revisar un directorios.
No existe una clase oficial para revisar directorios en carpetas pero vamos a ver algunas alternativas.
Es muy simple escribir una función que recorra todas las carpetas y subcarpetas:
import java.io.File
def subdirs(dir: File): Iterator[File] = {
val children = dir.listFiles.filter(_.isDirectory)
children.toIterator ++ children.toIterator.flatMap(subdirs _)
}
Con esta función se puede visitar todos los subdirectorios:
for (d <- subdirs(dir)) process d
Si utilizamos Java 7, se puede utilizar el metodo walkFileTree de la clase java.nio.file.Files. Esta clase hace uso de la interfaz FileVisitor. En scala se prefiere utilizar funciones de objetos y no interfaces. Por lo tanto podemos adaptar esta funcionalidad a una visión más scala:
import java.nio.file._
implicit def makeFileVisitor(f: (Path) => Unit) = new SimpleFileVisitor[Path] {
override def visitFile(p: Path, attrs: attribute.BasicFileAttributes) = {
f(p)
FileVisitResult.CONTINUE
}
}
Por lo tanto se pueden imprimir todos los directorios de esta manera:
Files.walkFileTree(dir.toPath, (f: Path) => println(f))
Si se quiere realizar otra acción, se pasara otro método y no println
Serialización.
Esto no tiene ninguna relación con los cereales (jeje). En Java, la serialización es utilizada para cuando queremos transmitir un objeto a otra maquina virtual o para guardar el objeto por un tiempo mínimo.
En scala se puede utilizar el mismo mecanismo pero su declaración es un tanto diferente:
Java:
public class Person implements java.io.Serializable {
private static final long serialVersionUID = 42L;
…
}
Scala:
@SerialVersionUID(42L) class Person extends Serializable
El Trait Serializable esta definido en el paquete scala por lo que no es necesario ningún import.
Si nos olvidamos de @SerialVersionUID este tomara un valor por defecto.
Serializar y desserializar un objeto es similar a Java:
val fred = new Person(...)
import java.io._
val out = new ObjectOutputStream(new FileOutputStream("/tmp/test.obj"))
out.writeObject(fred)
out.close()
val in = new ObjectInputStream(new FileInputStream("/tmp/test.obj"))
val savedFred = in.readObject().asInstanceOf[Person]
En scala las colecciones son seriabilizables por lo que se pueden utilizar como atributos de objetos seriabilizables:
class Person extends Serializable {
private val friends = new ArrayBuffer[Person] // OK—ArrayBuffer is serializable
…
}
Procesos de control
Tradicionalmente los administradores de sistema utilizan un script de shell para hacer tareas de mantenimiento como mover archivos o combinarlos. Los lenguajes script hacen fáciles estas tareas pero como lenguajes de programación dejan mucho que desear.
Scala fue diseñado para poder hacer desde humildes script a grandes aplicaciones. El paquete scala.sys.process provee utilidades para interactuar con programas shell. Es decir que podemos escribir programas tipo shell con scala.
Veamos un ejemplo simple:
import sys.process._
"ls -al .." !
Como resultado obtendremos el listado de todos los archivos del directorio. sys.process tiene un convertidor implícito de string al objeto ProcessBuilder. Y con el operador ! ejecutamos el comando.
El resultado del operador ! es un numero entero que si es 0 el comando tuvo éxito y si es distinto de 0, no.
Si utilizamos el operador !! esto retornara un string :
val result = "ls -al .." !!
Se puede utilizar este resultado como entrada de otros programas con el operador |# que es similar al operador | de linux:
"ls -al .." #| "grep sec" !
Se puede redireccionar la salida con el operador #>
"ls -al .." #> new File("output.txt") !
Si se desea que se agregar en el archivo se puede utilizar #>>
"ls -al .." #>> new File("output.txt") !
Y si se desea introducir una estrada se debe utilizar #<
"grep sec" #< new File("output.txt") !
Se puede introducir un input desde una URL :
"grep Scala" #< new URL("http://horstmann.com/index.html") !
Notemos que los operadores de scala se diferencian de los operadores bash solo porque comienzan con el carácter #.
sábado, 5 de agosto de 2017
Java y C caen en popularidad según el indice Tiobe
Bueno, yo la vi venir, los grandes ganadores en el indice Tiobe de los últimos años han bajado. Java y C han bajado bastante no para dejar el podio pero ha sido una gran sacudida, dado que venían estables o creciendo.
Si bien no soy capaz de opinar sobre C, me atrevo a opinar de Java y creo que la principal razón de su caída son :
Pero esta es solo mi opinión, veamos los números de agosto:
Lo extraño es que no hay un claro ganador, es como que se diversifico. Sera el fin de Java? Que piensan?
Dejo link:
https://www.tiobe.com/tiobe-index/
http://www.infoworld.com/article/3212970/application-development/java-and-c-hit-all-time-lows-in-tiobe-language-popularity-index.html
Si bien no soy capaz de opinar sobre C, me atrevo a opinar de Java y creo que la principal razón de su caída son :
- Los nuevos lenguajes que tiene la plataforma, como Kotlin, Scala, Groovy, Clojure y etc. Recordemos que ahora Kotlin es un lenguaje oficial para android.
- La plataforma .net esta ganando un lugar en el open source con .net core
Pero esta es solo mi opinión, veamos los números de agosto:
- Java (12.961%)
- C (6.477%)
- C++ (5.55%)
- C# (4.195%)
- Python (3.692%)
- Visual Basic .Net (2.569%)
- PHP (2.293%)
- JavaScript (2.098%)
- Perl (1.995%)
- Ruby (1.965%)
Claramente no se ve mucho la evolución pero en este gráfico queda super claro:
Lo extraño es que no hay un claro ganador, es como que se diversifico. Sera el fin de Java? Que piensan?
Dejo link:
https://www.tiobe.com/tiobe-index/
http://www.infoworld.com/article/3212970/application-development/java-and-c-hit-all-time-lows-in-tiobe-language-popularity-index.html
jueves, 3 de agosto de 2017
Donar
Agregue al Blog un botón para que puedan hacer donaciones al mismo, la idea es que con esas donaciones pueda comprar libros, hacer cursos y por supuesto que esto quede reflejado en el blog.
Si piensas que esto debe o puede mejorar o estas conforme pero quiere ir por más, dona unas divisas para poder seguir mejorando.
Saludos y gracias!!
Si piensas que esto debe o puede mejorar o estas conforme pero quiere ir por más, dona unas divisas para poder seguir mejorando.
Saludos y gracias!!
martes, 1 de agosto de 2017
Un resumen de Scala for the Impatient, parte 26
Leer una linea de archivo
Leer todas lineas desde un archivo, puede llamar al método getLine del Objeto scala.io.Source :
import scala.io.Source
val source = Source.fromFile("myfile.txt", "UTF-8")
// El primer argumento va ser un string or java.io.File
val lineIterator = source.getLines
El resultado es un iteraror que permite procesar las lineas:
for (l <- lineIterator) process l
o se puede volcar las lineas en un arreglo o en un buffer :
val lines = source.getLines.toArray
Algunas veces deseamos volcar el contenido de un archivo en un string, lo podemos hacer con :
val contents = source.mkString
Ojo! Cuando terminamos de usar source debemos cerrarlo.
Para leer caracteres podemos utilizar directamente source e iterar por le mismo:
for (c <- source) process c
Si deseamos leer un archivo (como istream :: peek en C ++ o PushbackInputStreamReader en Java), llama al método buffered en el origen
val source = Source.fromFile("myfile.txt", "UTF-8")
val iter = source.buffered
while (iter.hasNext) {
if (iter.head is nice)
process iter.next
else
…
}
source.close()
Veamos como podemos leer un todos lo espacios en nuestro código:
val tokens = source.mkString.split("\\s+")
Para convertir un String a entero o flotante se puede utilizar los métodos toInt o toDouble
Si necesitamos leer un entero desde la consola, podemos hacer lo siguiente:
print("Cuntos años tienes? ")
val age = readInt()
// O podemos usar readDouble o readLong
Este comando asume que el usuario ingresará un numero y si no lo hace se lanzara NumberFormatException
Leer url o otros recursos.
Para leer desde una Url o algun otro recurso podemos utilizar Source de la siguiente manera:
val source1 = Source.fromURL("http://horstmann.com", "UTF-8")
val source2 = Source.fromString("Hello, World!")
// lee desde un string, puede ser util para cuando se esta debugeando
val source3 = Source.stdin
// lee desde la entrada estandar
Leer archivos Binarios.
Para leer archivos binarios debemos utilizar la librería estándar de java. Veamos como podemos leer un archivo binario a un array de bytes:
val file = new File(filename)
val in = new FileInputStream(file)
val bytes = new Array[Byte](file.length.toInt)
in.read(bytes)
in.close()
Escribir un archivo de texto.
Scala no tiene un objeto o función especial para escribir archivos, debemos utilizar la librería de java. Por ejemplo:
val out = new PrintWriter("numbers.txt")
for (i <- 1 to 100) out.println(i)
out.close()
Todo funciona como se esperaba, excepto para el método printf. Cuando pasa un número a printf, el compilador se quejará de que necesita convertirlo a un AnyRef:
out.printf("%6d %10.2f",
quantity.asInstanceOf[AnyRef], price.asInstanceOf[AnyRef])
pero podemos usar el método de formato de la clase String:
out.print("%6d %10.2f".format(quantity, price))
Suscribirse a:
Entradas (Atom)