stringtranslate.com

Programación tácita

La programación tácita , también llamada estilo sin puntos , es un paradigma de programación en el que las definiciones de funciones no identifican los argumentos (o "puntos") sobre los que operan. En cambio, las definiciones simplemente componen otras funciones, entre las que se encuentran combinadores que manipulan los argumentos. La programación tácita es de interés teórico, porque el uso estricto de la composición da como resultado programas que se adaptan bien al razonamiento ecuacional . [1] También es el estilo natural de ciertos lenguajes de programación , incluidos APL y sus derivados, [2] y lenguajes concatenativo como Forth . La falta de denominación de argumentos le da al estilo sin puntos una reputación de ser innecesariamente oscuro, de ahí el epíteto de "estilo sin puntos". [1]

Los scripts de Unix utilizan el paradigma con tuberías .

Ejemplos

Pitón

La programación tácita se puede ilustrar con el siguiente código Python . Una secuencia de operaciones como la siguiente:

def  ejemplo ( x ):  return  baz ( bar ( foo ( x )))

... puede escribirse en estilo libre de puntos como la composición de una secuencia de funciones, sin parámetros: [3]

de  functools  importar  parcial ,  reducir def  componer ( * fns ):  devolver  parcial ( reducir ,  lambda  v ,  fn :  fn ( v ),  fns )ejemplo  =  componer ( foo ,  bar ,  baz )

Para un ejemplo más complejo, el código Haskell p = ((.) f) . gse puede traducir como:

p  =  parcial ( componer ,  parcial ( componer ,  f ),  g )

Programación funcional

Un ejemplo sencillo (en Haskell ) es un programa que calcula la suma de una lista de números. Podemos definir la función suma de forma recursiva utilizando un estilo puntual (cf. programación a nivel de valores ) como:

suma ( x : xs ) = x + suma xs suma [] = 0         

Sin embargo, utilizando un pliegue podemos reemplazar esto con:

suma xs = foldr ( + ) 0 xs      

Y entonces el argumento no es necesario, por lo que esto se simplifica a

suma = foldr ( + ) 0    

que no tiene puntos.

Otro ejemplo utiliza la composición de funciones :

pxyz = f ( gxy ) z         

El siguiente pseudocódigo similar a Haskell expone cómo reducir una definición de función a su equivalente sin puntos:

p = \ x -> \ y -> \ z -> f ( g x y ) z = \ x -> \ y -> f ( g x y ) = \ x -> \ y -> ( f . ( g x )) y = \ x -> f . ( g x ) ( * Aquí se utiliza el operador de composición infijo "." como una función currificada . * ) = \ x -> (( . ) f ) ( g x ) = \ x -> ((( . ) f ) . g ) x                                                                   p = (( . ) f ) . g     

Finalmente, para ver un ejemplo complejo, imaginemos un programa de filtro de mapas que toma una lista, le aplica una función y luego filtra los elementos según un criterio.

lista de operadores de criterios mf = criterios de filtro ( lista de operadores de mapa )         

Puede expresarse sin puntos [4] como

mf = ( . mapa ) . ( . ) . filtro       

Obsérvese que, como se indicó anteriormente, los puntos en "sin puntos" se refieren a los argumentos, no al uso de puntos; un error común. [5]

Se han escrito algunos programas para convertir automáticamente una expresión Haskell a una forma sin puntos.

Familia APL

En J , el mismo tipo de código sin puntos aparece en una función creada para calcular el promedio de una lista (matriz) de números:

promedio =: +/ % #   

+/suma los elementos de la matriz asignando ( /) suma ( +) a la matriz. %divide la suma por el número de elementos ( #) en la matriz.

La fórmula de Euler expresada tácitamente:

porque =: 2 o . ] pecado =: 1 o . ] Euler =: ^@ j . = porque j . pecado              

( j.es una función primitiva cuya definición monádica es 0j1multiplicada por x y cuya definición diádica es x+0j1×y.) Los mismos cálculos tácitos expresados ​​en Dyalog APL :

promedio + ÷     cos 2 sin 1 EulerCalc cos + 0j1 × sin ⍝ 0j1 es lo que usualmente se escribe como i EulerDirect * 0J1 ×⊢ ⍝ Igual que ¯12○⊢ ⍝ ¿Los 2 métodos producen el mismo resultado? EulerCheck EulerDirect = EulerCalc EulerCheck ¯1 1 2 3 1 1 1 1 ⍝ ¡Sí, hasta ahora todo bien!                          

Basado en pila

En los lenguajes de programación orientados a la pila (y en los concatenativo , la mayoría de los cuales se basan en la pila [ cita requerida ] ), se utilizan comúnmente métodos sin puntos. Por ejemplo, un procedimiento para calcular los números de Fibonacci podría verse como el siguiente en PostScript :

/fib { dup dup 1 eq intercambio 0 eq o no { dup 1 sub fib intercambio 2 sub fib agregar } si } def                      

Tuberías

Tubería de Unix

En los scripts de Unix, las funciones son programas informáticos que reciben datos de la entrada estándar y envían los resultados a la salida estándar . Por ejemplo,

ordenar | uniq -c | ordenar -rn      

es una composición tácita o sin puntos que devuelve los recuentos de sus argumentos y los argumentos, en orden de recuento decreciente. 'sort' y 'uniq' son las funciones, '-c' y '-rn' controlan las funciones, pero no se mencionan los argumentos. La barra vertical '|' es el operador de composición.

Debido a la forma en que funcionan las canalizaciones, normalmente solo es posible pasar un "argumento" a la vez en forma de un par de secuencias de entrada/salida estándar. Aunque se pueden abrir descriptores de archivos adicionales desde canalizaciones con nombre , esto ya no constituye un estilo sin puntos.

yo q

jq es un lenguaje de programación orientado a JSON en el que se utiliza el símbolo '|' para conectar filtros y formar una secuencia de comandos de una forma habitual. Por ejemplo:

 [1,2] | añadir

evalúa a 3. (Sí, la matriz JSON es un filtro jq que evalúa a una matriz).

Aunque son similares a las canalizaciones de Unix, las canalizaciones de jq permiten enviar los datos entrantes a más de un destinatario en el lado derecho del '|' como si fuera en paralelo. Por ejemplo, el programa `add/length` calculará el promedio de los números en una matriz, de modo que:

 [1,2] | añadir/longitud

evalúa a 1,5

Similarmente:

 [1,2] | [longitud, añadir, añadir/longitud]

evalúa a [2,3,1.5]

Se puede utilizar un punto ('.') para definir un punto de conexión en el lado derecho, por ejemplo:

 1 | [., .]

evalúa a [1,1]

y de manera similar:

 2 | poder(.; .)

se evalúa como 4 ya que pow(x;y) es x elevado a y.

Secuencia de Fibonacci

Un programa jq tácito para generar la secuencia de Fibonacci sería:

 [0,1] | recurse( [último, agregar] ) | primero

Aquí, [0,1] es el par inicial que se debe tomar como los dos primeros elementos de la secuencia de Fibonacci. (El par [1,1] también se podría utilizar para la definición de la variante).

Los tokens alfabéticos son filtros incorporados: `first` y `last` emiten el primer y último elemento de sus matrices de entrada respectivamente; y `recurse(f)` aplica un filtro, f, a su entrada de forma recursiva.

jq también permite definir nuevos filtros en un estilo tácito, por ejemplo:

 def fib: [0,1] | recurse( [último, agregar] ) | primero;
Composición de funciones unarias

En la sección sobre Python de este artículo, se considera la siguiente definición de Python:

def  ejemplo ( x ):  return  baz ( bar ( foo ( x )))

En un estilo sin puntos, esto podría escribirse en Python como:

ejemplo  =  componer ( foo ,  bar ,  baz )

En jq, la definición equivalente sin puntos sería:

 def ejemplo: foo | bar | baz;

Véase también

Referencias

  1. ^ ab Manuel Alcino Pereira da Cunha (2005) Cálculo del programa sin puntos
  2. ^ W. Neville Holmes, ed. (2006) Computadoras y personas
  3. ^ "Código de nombre, no valores". Concatenative.org . Consultado el 13 de septiembre de 2013 .
  4. ^ correo de piper
  5. ^ "Pointfree - HaskellWiki". wiki.haskell.org . Consultado el 5 de junio de 2016 .

Enlaces externos