Ruby é uma linguagem funcional?

87

A Wikipedia diz que Ruby é uma linguagem funcional, mas não estou convencido. Por que ou por que não?

Esteban Araya
fonte
4
Provavelmente porque sua pergunta é muito curta, embora pessoalmente eu não tenha nenhum problema com ela!
ljs 01 de
Já existem boas respostas, apenas para complementá-las, um par de conteúdos que discutem FP e Ruby: code.google.com/p/tokland/wiki/RubyFunctionalProgramming slideshare.net/tokland/functional-programming-with-ruby-9975242
Tóquio
1
Se alguém estiver interessado neste tópico, por favor assista e você aprenderá como o Ruby pode ser usado de forma funcional, quais são as raízes da programação funcional, porque o Ruby não é uma linguagem funcional mesmo que seja capaz de programar funcionalmente: youtube .com / watch? v = 5ZjwEPupybw
maddin2code

Respostas:

29

Eu definitivamente acho que você pode usar um estilo funcional em Ruby.

Um dos aspectos mais críticos para poder programar em um estilo funcional é se a linguagem suporta funções de ordem superior ... o que Ruby faz.

Dito isso, é fácil programar em Ruby em um estilo não funcional também. Outro aspecto importante do estilo funcional é não ter estado e ter funções matemáticas reais que sempre retornam o mesmo valor para um determinado conjunto de entradas. Isso pode ser feito em Ruby, mas não é imposto na linguagem como algo mais estritamente funcional como Haskell.

Então, sim, ele suporta um estilo funcional, mas também permite que você programe em um estilo não funcional.

Mike Stone
fonte
4
Usando este critério, você diria que Smalltalk é funcional porque tem blocos?
OscarRyz
Boa resposta, mas um detalhe - funções de ordem superior não são estritamente necessárias para um estilo funcional. por exemplo, você pode obter um estilo funcional em Java (que não tem funções de primeira classe / ordem superior) definindo objetos de função e compondo-os para obter o mesmo efeito de uma função de ordem superior.
mikera
2
Quero apenas afirmar que @peter perguntou Is ruby a functional language?e em uma resposta direta é um simples não. Ruby é uma linguagem orientada a objetos com alguns recursos funcionais.
Elias Perez
58

Não importa se uma linguagem é ou não funcional. A Programação Funcional é uma tese, melhor explicada por Philip Wadler (The Essence of Functional Programming) e John Hughes (Why Functional Programming Matters).

Uma pergunta significativa é, 'Quão receptiva é Ruby para alcançar a tese de programação funcional?' A resposta é 'muito mal'.

Eu dei uma palestra sobre isso recentemente. Aqui estão os slides.

Tony Morris
fonte
3
Os slides que você deu não mencionaram por que Ruby é "muito pouco receptiva à realização da tese de FP". Por que C # é mais acessível do que Java (OK, funções anônimas mais fáceis?)? É porque você pode ter variáveis ​​globais em Ruby?
kizzx2
7
Não, os slides não entram em detalhes, pois este é um tópico bastante extenso. Correndo o risco de simplificação excessiva, por exemplo, Ruby impõe um modelo de avaliação (chamada por valor) que garante a não composição dos programas. As implicações disso podem ser facilmente subestimadas. Ruby também está casado com a ideia de que um programa é uma sequência de efeitos. Ou seja, Ruby sai de seu caminho para tornar difícil / intratável o uso de qualquer outro modelo computacional. Espero que este breve comentário ajude.
Tony Morris
2
1 para apontar a ambigüidade na classificação de linguagens como funcionais. Inferno, eu escrevi C funcional!
Eli,
1
Por que C # é mais receptivo que Ruby?
dan_l
1
Efetivamente, uma resposta apenas de link, pois terceiriza a parte crítica da explicação (a explicação inteira, na verdade) para um link externo. Agora que o link morreu, a resposta se tornou inútil.
ivan_pozdeev
34

Ruby oferece suporte a funções de nível superior (consulte Array # map, injetar e selecionar), mas ainda é uma linguagem orientada a objetos imperativa.

Uma das principais características de uma linguagem funcional é evitar o estado mutável. Linguagens funcionais não têm o conceito de variável como você teria em Ruby, C, Java ou qualquer outra linguagem imperativa.

Outra característica fundamental de uma linguagem funcional é que ela se concentra na definição de um programa em termos de "o quê", ao invés de "como". Ao programar em uma linguagem OO, escrevemos classes e métodos para ocultar a implementação (o "como") do "o quê" (o nome da classe / método), mas no final esses métodos ainda são escritos usando uma sequência de instruções. Em uma linguagem funcional, você não especifica uma sequência de execução, mesmo no nível mais baixo.

Mike
fonte
3
Concordo com a maior parte de sua afirmação, no entanto, discordo sobre "Linguagens funcionais não têm o conceito de variáveis ​​como você teria em Java etc." No haskell, você pode usar variáveis ​​em funções puras, você pode até atribuir uma função a uma variável, a maior diferença é que uma vez que uma variável é atribuída, ela não pode ser modificada posteriormente.
HHC
6
HHC, por definição, uma variável é um valor que pode mudar . Você está falando de valores.
Scala Newb
Na verdade, as "variáveis ​​não modificáveis" de Haskell são apenas funções constantes sem parâmetros (definições).
raindev
16

Eu sugiro que apoiar ou ter a capacidade de programar em uma linguagem em um estilo funcional não significa uma linguagem funcional.

Eu posso até escrever o código Java em um estilo funcional, se eu quiser ferir os meus colegas e eu mesmo alguns meses semanas diante.

Ter uma linguagem funcional não é apenas sobre o que você pode fazer, como funções de ordem superior, funções de primeira classe e currying. É também sobre o que você não pode fazer, como efeitos colaterais em funções puras.

Isso é importante porque é uma grande parte da razão pela qual os programas funcionais são, ou o código funcional em geral é, mais fácil de raciocinar. E quando é mais fácil raciocinar sobre o código, os bugs tornam-se mais superficiais e flutuam até a superfície conceitual onde podem ser corrigidos, o que, por sua vez, resulta em código menos problemático.

Ruby é orientado a objetos em seu núcleo, então, embora tenha um suporte razoavelmente bom para um estilo funcional, ele não é uma linguagem funcional.

Essa é a minha opinião não científica de qualquer maneira.

Editar: Em retrospecto e com consideração pelos bons comentários que recebi a esta resposta até agora, acho que a comparação orientada a objeto versus funcional é uma de maçãs e laranjas.

O verdadeiro diferenciador é ser imparcial na execução, ou não. As linguagens funcionais têm a expressão como sua construção linguística primária e a ordem de execução é freqüentemente indefinida ou definida como preguiçosa. A execução estrita é possível, mas usada apenas quando necessário. Em uma linguagem imparcial, a execução estrita é o padrão e, embora a execução lenta seja possível, costuma ser complicada de fazer e pode ter resultados imprevisíveis em muitos casos extremos.

Agora, essa é minha opinião não científica.

Colete chris
fonte
Acho que você pode fazer um caso muito melhor para chamar Ruby de funcional do que Java ... não, Ruby não é estritamente funcional, mas é muito fácil de usar um estilo funcional nele ... e um colega de estilo não funcional pode altere-o facilmente de volta para não funcional
Mike Stone,
1
Sim, Mike, se você deseja codificar em um estilo funcional, Ruby é uma grande melhoria em relação ao Java. Eu estava usando Java apenas para exagerar e enfatizar o ponto de vista.
Chris Vest,
Então, como D tem funções puras, você chamaria D de uma linguagem funcional? digitalmars.com/d/2.0/function.html#pure-functions
Peter Burns,
3
Muitas pessoas consideram as linguagens funcionais Lisp e Scheme, em grande parte devido ao uso generalizado de funções anônimas. E, no entanto, eles não têm funções puras garantidas. Limitar o termo a linguagens que suportam funções puras parece muito restritivo.
skymt
13

Ruby terá que atender aos seguintes requisitos para ser "VERDADEIRAMENTE" funcional.

Valores imutáveis: uma vez que uma “variável” é definida, ela não pode ser alterada. Em Ruby, isso significa que você efetivamente tem que tratar as variáveis ​​como constantes. O não é totalmente suportado no idioma, você terá que congelar cada variável manualmente.

Sem efeitos colaterais: quando passado um determinado valor, uma função deve sempre retornar o mesmo resultado. Isso anda de mãos dadas com valores imutáveis; uma função nunca pode pegar um valor e alterá-lo, pois isso estaria causando um efeito colateral tangencial ao retorno de um resultado.

Funções de ordem superior: são funções que permitem funções como argumentos ou usam funções como valor de retorno. Esta é, sem dúvida, uma das características mais críticas de qualquer linguagem funcional.

Currying: ativado por funções de ordem superior, currying é transformar uma função que recebe vários argumentos em uma função que leva um argumento. Isso anda de mãos dadas com a aplicação de função parcial, que está transformando uma função com vários argumentos em uma função que recebe menos argumentos do que originalmente.

Recursão: looping chamando uma função de dentro de si mesmo. Quando você não tem acesso a dados mutáveis, a recursão é usada para construir e encadear a construção de dados. Isso ocorre porque o loop não é um conceito funcional, pois requer a passagem de variáveis ​​para armazenar o estado do loop em um determinado momento.

Avaliação preguiçosa ou avaliação adiada: atrasando o processamento de valores até o momento em que é realmente necessário. Se, por exemplo, você tiver algum código que gerou uma lista de números de Fibonacci com a avaliação preguiçosa habilitada, isso não seria realmente processado e calculado até que um dos valores no resultado fosse exigido por outra função, como puts.

Proposta (só uma ideia) Seria ótimo ter algum tipo de definição para ter uma modediretiva para declarar arquivos com paradigma funcional, exemplo

modo 'funcional'

Elias Perez
fonte
2
Você é bem vindo. Eu gostaria de convidar você a ler sobre linguagens funcionais. Lisp sendo o avô de todas as linguagens funcionais, ML (CAML) e Erlang / Elixir. Isso realmente muda sua perspectiva das coisas. Não sou nenhum especialista, mas um estudante constante de ciência da computação, gosto de ler e aprender coisas novas.
Elias Perez
Resposta bem organizada. Teria adorado alguma exploração adicional de quão bem o ruby ​​suporta essas coisas. Acredito que funções de ordem superior, currying e recursão são todas suportadas / possíveis no ruby, corrija-me se estiver errado.
Michael Dorst
9

Ruby é uma linguagem multiparadigma que suporta um estilo funcional de programação.

skymt
fonte
8
fornecer evidências
Mirzhan Irkegulov
4

Ruby é uma linguagem orientada a objetos, que pode suportar outros paradigmas (funcional, imperativo, etc). No entanto, como tudo em Ruby é um objeto, é principalmente uma linguagem OO.

exemplo:

"hello" .reverse () = "olleh", cada string é uma instância do objeto string e assim por diante.

Leia aqui ou aqui

camflan
fonte
Eu nunca entendi realmente como "tudo é um objeto" torna Ruby mais OO. Eu concordo que Ruby é principalmente OO, mas "tudo é um objeto" realmente significa apenas que não existem tipos "primitivos", o que tem muito pouca relação com a capacidade do desenvolvedor de escrever programas no estilo OO, dado que a existência de primitivos tipos geralmente significa apenas que existem quatro ou cinco tipos que não possuem nenhum método.
Michael Dorst
4

Depende da sua definição de “linguagem funcional”. Pessoalmente, acho que o próprio termo é bastante problemático quando usado como um absoluto. Existem mais aspectos em ser uma “linguagem funcional” do que meros recursos de linguagem e a maioria depende de onde você está olhando. Por exemplo, a cultura em torno da língua é muito importante nesse aspecto. Encoraja um estilo funcional? E as bibliotecas disponíveis? Eles encorajam você a usá-los de uma forma funcional?

A maioria das pessoas chamaria Scheme de uma linguagem funcional, por exemplo. Mas e quanto ao Common Lisp? Além do problema de namespace múltiplo / único e eliminação garantida de chamada final (que algumas implementações de CL também suportam, dependendo das configurações do compilador), não há muito que torne Scheme uma linguagem mais adequada para programação funcional do que Common Lisp, e ainda assim, a maioria dos Lispers não chamaria CL de linguagem funcional. Por quê? Porque a cultura que o cerca depende muito dos recursos imperativos do CL (como a macro LOOP, por exemplo, que a maioria dos planejadores provavelmente desaprovaria).

Por outro lado, um programador C pode muito bem considerar CL uma linguagem funcional. Afinal, a maior parte do código escrito em qualquer dialeto Lisp é certamente muito mais funcional em estilo do que seu bloco normal de código C. Da mesma forma, Scheme é uma linguagem imperativa em comparação com Haskell. Portanto, não acho que possa haver uma resposta definitiva sim / não. Chamar uma linguagem de funcional ou não depende muito do seu ponto de vista.

Matthias Benkard
fonte
De que forma Haskell não é uma linguagem puramente funcional? Ou que tal Miranda (uma linguagem de programação funcional menos conhecida)? course.cs.washington.edu/courses/cse505/99au/functional/… "Haskell é uma linguagem funcional pura padrão,"
barlop
2

Ruby também não é uma linguagem multiparadigma, eu acho. O multiparadigma tende a ser usado por pessoas que desejam rotular sua linguagem favorita como algo útil em muitas áreas diferentes.

Eu descreveria que Ruby é uma linguagem de script orientada a objetos. Sim, funções são objetos de primeira classe (mais ou menos), mas isso realmente não a torna uma linguagem funcional. IMO, devo acrescentar.

JesperE
fonte
4
O tipo de linguagem é definido pelos estilos de programação que ela suporta; que, por sua vez, é decidido pelas características que possui. Funções de primeira classe e anônimas = programação funcional mínima. Ruby suporta programação OO, mas não exige: você nunca precisa definir uma classe. Portanto, multiparadigma.
skymt 01 de
2

A recursão é comum na programação funcional. Quase todas as linguagens oferecem suporte à recursão, mas os algoritmos recursivos geralmente são ineficazes se não houver otimização de chamada final (TCO).

Linguagens de programação funcional são capazes de otimizar a recursão da cauda e podem executar esse código em espaço constante. Algumas implementações Ruby otimizam a recursão de cauda, ​​as outras não, mas em geral as implementações Ruby não são obrigadas a fazer o TCO. Consulte Ruby executa otimização de chamada de cauda?

Portanto, se você escrever algum estilo funcional Ruby e contar com o TCO de alguma implementação específica, seu código pode ser muito ineficaz em outro interpretador Ruby. Acho que é por isso que Ruby não é uma linguagem funcional (nem Python).

sastanina
fonte
O TCO é interessante, porque essencialmente muda o comportamento do programa. Em certos casos, isso não é visível para o programa, mas em outros casos, é, por exemplo, backtraces de exceção. Portanto, nem sempre é uma otimização adequada.
ioquatix
2

A rigor, não faz sentido descrever uma linguagem como "funcional"; a maioria das linguagens são capazes de programação funcional. Até mesmo C ++ é.

O estilo funcional é mais ou menos um subconjunto de recursos de linguagem imperativos, suportado com açúcar sintático e algumas otimizações do compilador, como imutabilidade e nivelamento de recursão de cauda,

O último, sem dúvida, é um detalhe técnico específico da implementação e não tem nada a ver com a linguagem real. O compilador x64 C # 4.0 faz otimização de recursão de cauda, ​​enquanto o x86 não faz por algum motivo estúpido.

O açúcar sintático geralmente pode ser contornado de uma forma ou de outra, especialmente se a linguagem tiver um pré-compilador programável (isto é, o #define do C).

Pode ser um pouco mais significativo perguntar, "a linguagem __ suporta programação imperativa?", E a resposta, por exemplo, com Lisp, é "não".

Rei Miyasaka
fonte
1

Por favor, dê uma olhada no início do livro: "A-Great-Ruby-eBook" . Ele discute o tópico muito específico que você está perguntando. Você pode fazer diferentes tipos de programação em Ruby. Se você deseja programar funcionalmente, pode fazê-lo. Se você quiser programar imperativamente, você pode fazê-lo. É uma questão de definição de quão funcional o Ruby é no final das contas. Por favor, veja a resposta do usuário camflan.

Léo Léopold Hertz 준영
fonte