"¡FP en Python con Coconut!" |> imprimir

Esta publicación presenta el lenguaje Coconut, un superconjunto funcional del lenguaje Python, que tiene como objetivo crear código elegante y funcional mientras permanece en un entorno y bibliotecas Python familiares, y proporciona algunos ejemplos ilustrativos.





", !" |> x -> x.replace('', 'Coconut') |> print
      
      



El lenguaje Coconut (en el momento de escribir este artículo, su última versión es la v1.5.0) es un superconjunto estricto orientado a funciones del lenguaje Python y, por lo tanto, todo lo que es válido para Python también es válido para Coconut, mientras que Coconut se transpila a Pitón. De hecho, Coconut es un campo de juego para dominar el paradigma de la programación funcional, probar ideas en el campo de la PF, practicar técnicas de resolución de problemas en este paradigma y con fines educativos.





La página del sitio web en el idioma indica que Coconut está diseñado para serle útil. Coconut amplía el repertorio del programador de Python al aprovechar las herramientas de la programación funcional moderna, lo que hace que estas herramientas sean más fáciles de usar y más potentes. En otras palabras, Coconut hace con la programación funcional lo que Python hizo con la programación imperativa.





Con suerte, esta publicación prueba estas afirmaciones en la práctica.





Por si acaso, puede instalar Coconut usando el administrador de paquetes pip: pip install coconut







Coconut es un superconjunto estricto del lenguaje Python

Escribir código Python en un estilo funcional puede ser complicado, desde pequeños inconvenientes, como la sintaxis lambda detallada, hasta problemas más serios, como el encadenamiento de iteradores calculados de forma perezosa y la coincidencia de patrones. Coconut es un superconjunto funcional del lenguaje Python que tiene como objetivo crear un código elegante y funcional al estilo Python.





, Python . Python -, , . , . , .





2016 Python , - , Haskell Scala. Coconut , Python. , . , print(", !")



", !" |> print



. , Python, , (x) -> x2



lambda x: x2



.





, Coconut:









match [head] + tail in [0, 1, 2, 3]:
    print(head, tail)
      
      







data Empty()
data Leaf(n)
data Node(l, r)

def size(Empty()) = 0

addpattern def size(Leaf(n)) = 1

addpattern def size(Node(l, r)) = size(l) + size(r)
      
      







{"list": [0] + rest} = {"list": [0, 1, 2, 3]}
      
      







range(10) |> map$(pow$(?, 2)) |> list
      
      







(| first_elem() |) :: rest_elems()
      
      







(f..g..h)(x, y, z)
      
      







x -> x ** 2
      
      







5 `mod` 3 == 2
      
      







", !" |> x -> x.replace('', 'Coconut') |> print
      
      







product = reduce$(*)
      
      







def factorial(n, acc=1):
    case n:
        match 0:
            return acc
        match _ is int if n > 0:
            return factorial(n-1, acc*n)
      
      







range(100) |> parallel_map$(pow$(2)) |> list
      
      



coconut-develop



(pip install coconut-develop



) Python 3.10, Coconut. Coconut v1.6.0.





Coconut Python Coconut :





, Python, Coconut . , , , , Coconut , , , : Coconut Python, Python, Coconut.





coconut - , Python, . Python Coconut, , Python — - Python.





, Python , Coconut . , .





(Sieve of Eratosthenes) - n, . , , , . , ( ) .





Python

Python : primes



sieve



. primes



sieve



.





from itertools import count, takewhile

def primes():
    def sieve(numbers):
        head = next(numbers)
        yield head
        yield from sieve(n for n in numbers if n % head)
    return sieve(count(2))

list(takewhile(lambda x: x < 60, primes()))
      
      



[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59]
      
      



sieve



count



, , 2 . sieve



(yield



) . (yield from



) sieve



, .





, numbers



next(numbers)



numbers



n for n in numbers if n % head



. , next



- : , .





list



, takewhile



, list



.





, - : , ..





Python Coconut

7 « »() Python Coconut.





1. lambda





lambda



->



.





from itertools import count, takewhile

def primes():
    def sieve(numbers):
        head = next(numbers)
        yield head
        yield from sieve(n for n in numbers if n % head)
    return sieve(count(2))

list(takewhile(x -> x < 60, primes()))
      
      



2.





f(g(h(d)))



-: d -> h -> g -> f



|>



.





from itertools import count, takewhile

def primes():
    def sieve(numbers):
        head = next(numbers)
        yield head
        yield from sieve(n for n in numbers if n % head)
    return sieve(count(2))

primes() |> ns -> takewhile(x -> x < 60, ns) |> list
      
      



3.





, , - . $



.





from itertools import count, takewhile

def primes():
    def sieve(numbers):
        head = next(numbers)
        yield head
        yield from sieve(n for n in numbers if n % head)
    return sieve(count(2))

primes() |> takewhile$(x -> x < 60) |> list
      
      



4.





, yield



, yield



yield from



. , ::



.





from itertools import count, takewhile

def primes():
    def sieve(numbers):
        head = next(numbers)
        return [head] :: sieve(n for n in numbers if n % head)
    return sieve(count(2))

primes() |> takewhile$(x -> x < 60) |> list
      
      



5.





, , , , . ::



, . , .





from itertools import count, takewhile

def primes():
    def sieve([head] :: tail):
        return [head] :: sieve(n for n in tail if n % head)
    return sieve(count(2))

primes() |> takewhile$(x -> x < 60) |> list
      
      



6.





. , . return



=



:



.





from itertools import count, takewhile

def primes() =
    def sieve([x] :: xs) = [x] :: sieve(n for n in xs if n % x)
    sieve(count(2))

primes() |> takewhile$(x -> x < 60) |> list
      
      



7.





, import



. , .. .





def primes() =
    def sieve([x] :: xs) = [x] :: sieve(n for n in xs if n % x)
    sieve(count(2))

primes() |> takewhile$(x -> x < 60) |> list
      
      



[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59]
      
      



. : primes



sieve



, sieve



. :





from itertools import count, takewhile

def primes():
    def sieve(numbers):
        head = next(numbers)
        yield head
        yield from sieve(n for n in numbers if n % head)
    return sieve(count(2))

list(takewhile(lambda x: x < 60, primes()))
      
      



:





def primes() =
    def sieve([x] :: xs) = [x] :: sieve(n for n in xs if n % x)
    sieve(count(2))

primes() |> takewhile$(x -> x < 60) |> list
      
      



, Coconut Haskell:





primes :: [Int]
primes = sieve [2..]
where
    sieve (x :: xs) = x : sieve (filter (\n -> n `rem` x /= 0) xs
    sieve []        = []
                                 
?> takewhile (<60) primes 
      
      







def quick_sort([]) = []

@addpattern(quick_sort)
def quick_sort([head] + tail) =
    """ , 
      ."""
    (quick_sort([x for x in tail if x < head])
    + [head]
    + quick_sort([x for x in tail if x >= head]))
    
quick_sort([3,6,9,2,7,0,1,4,7,8,3,5,6,7])
      
      



[0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 7, 7, 8, 9]
      
      







def factorial(0, acc=1) = acc

@addpattern(factorial)
def factorial(n is int, acc=1 if n > 0) =
    """ n!,  n -    >= 0."""
    factorial(n-1, acc*n)

def is_even(0) = True

@addpattern(is_even)
def is_even(n is int if n > 0) = is_odd(n-1)
def is_odd(0) = False

@addpattern(is_odd)
def is_odd(n is int if n > 0) = is_even(n-1)

factorial(6)  # 720
      
      







@recursive_iterator
def fib_seq() =
    """   ."""
    (1, 1) :: map((+), fib_seq(), fib_seq()$[1:])
            
fib_seq()$[:10] |> parallel_map$(pow$(?, 2)) |> list
      
      



[1, 1, 4, 9, 25, 64, 169, 441, 1156, 3025]
      
      







def zipwith(f, *args) =
    zip(*args) |> map$(items -> f(*items))
    
list(zipwith(lambda x: x > 4, [1,2,3,4,5,6,7,8,9,0]))
      
      



[False, False, False, False, True, True, True, True, True, False]
      
      



Espero que la claridad de los ejemplos anteriores despierte el interés de los lectores y los anime a participar en un estudio más profundo del paradigma de la planificación familiar. De hecho, Coconut ofrece azúcar sintáctica, es decir, una serie de optimizaciones de codificación de código que hacen que el código sea funcional al ser un campo de juego para probar ideas utilizando el paradigma de programación funcional.





Materiales de referencia:





  • Sitio web de idiomas





  • Tutorial





  • Documentación





  • Repositorio de Github





  • Intérprete en línea





La publicación se preparó utilizando información del sitio web de idiomas y materiales de Anthony Kwong.








All Articles