A programação funcional é apenas diferente ou é realmente mais difícil?

12

A programação funcional é apenas diferente ou é realmente mais difícil ?

Diga alguém que nunca aprendeu a programar antes e que tenha aprendido programação funcional. vs alguém que nunca aprendeu programação antes e que é ensinado programação imperativa. qual ele achará mais difícil? ou o mesmo?

Minha pergunta: digamos que o problema agora é colocar uma entrada de camelo,

tal que qwe_asd_zxc_rty_fgh_vbnse tornaqweAsdZxcRtyFghVbn

A maneira processual é:

  1. dividi-lo ao longo do _
  2. percorrer a matriz pulando o primeiro item
  3. para cada entrada colocamos em maiúscula a primeira letra
  4. junte os resultados

A maneira funcional é:

  1. se não conseguir encontrar _retornoinput
  2. cortar ao inputlongo do primeiro _(de modo que obtemos qwee asd_zxc_rty_gfh_cvb)
  3. colocar em maiúscula a primeira letra heade concordar comf(tail)

Ok, se você tem um background funcional E tem uma experiência substancial em programação processual, eu gostaria de perguntar: você levará mais tempo para descobrir a maneira processual ou levará mais tempo para você descobrir a maneira funcional?

Se você possui experiência em procedimentos, mas tem muitos anos de experiência em programação funcional, gostaria de fazer a mesma pergunta: você levará mais tempo para descobrir a maneira processual ou levará mais tempo para você descobrir a funcionalidade caminho?

Pacerier
fonte
5
Ehrm, a "maneira processual" me parece perfeitamente funcional se usarmos mappara a etapa 3 em vez de um loop mutante. A segunda abordagem é algo que eu consideraria apenas se não houver uma função dividida na biblioteca padrão (nesse caso, ela deve ser comparada a uma solução imperativa que também não usa split).
sepp2k
8
Não há nada especificamente funcional ou processual em nenhum dos seus exemplos. Parece-me que você está tentando extrapolar a partir de um entendimento incorreto da programação funcional. Não é de admirar que você esteja obtendo resultados incomuns.
Rein Henrichs
Não acho que a programação funcional seja difícil, apenas diferente. Se você também não tem experiência em programação, é tão fácil de aprender, mas, por algum motivo, depois de aprender a programação imperativa, a programação funcional se torna difícil.
dan_waterworth
1
Eu acho que a distinção entre funcional e processual se torna discutível, já que linguagens de fluxo principal como JavaScript, C # e Groovy contêm recursos cada vez mais funcionais.
user281377
2
A programação imperativa é muito mais difícil e contra-intuitiva para aqueles que não tinham experiência anterior em programação. Uma expressão como x=x+1pode explodir um cérebro inesperado. A programação funcional é natural, nada mais é que funções estritamente matemáticas puras e convenientes.
SK-logic

Respostas:

12

Apenas diferente. A programação funcional está muito mais intimamente relacionada à matemática, com a qual a maioria das pessoas está familiarizada. A coisa toda sobre "variáveis ​​imutáveis" só choca os programadores imperativos, onde a mentalidade "mutável" está profundamente arraigada.

Para os novatos, geralmente é bastante intuitivo que você não possa simplesmente mudar o valor de algo.

Onde estudei CS, aprendemos uma linguagem funcional como nosso primeiro curso. E todos que haviam aprendido C ++ ou Java anteriormente lutavam com isso. Aqueles que eram novos na programação entenderam com bastante facilidade.

jalf
fonte
jalf você é um daqueles iniciantes em programação e aprendeu com bastante facilidade?
Pacerier
Eu estava em algum lugar no meio. Eu tinha mexido um pouco com C ++ e PHP antes disso, mas não o suficiente para realmente me acostumar com a mentalidade imperativa. O padrão era bastante claro quando você olhava para a classe como um todo. Além disso, este foi quase uma década atrás, então não, eu não sou muito novo para programação de hoje;)
jalf
Variáveis ​​imutáveis? O mathematica não é uma linguagem de programação funcional? variáveis ​​no mathematica são certamente mutáveis, não?
user56834
20

É apenas diferente

Quando você programa, traduz essencialmente a maneira como raciocina em código, pode-se dizer que a distância entre seus pensamentos e a solução final é a "lacuna cognitiva". Quanto maior a diferença, mais difícil será para você preencher essa lacuna.

Se você tem experiência em procedimentos, terá se treinado para pensar em procedimentos, para que a diferença seja menor que no código funcional e vice-versa.

A única maneira de um paradigma de programação ser intrinsecamente mais fácil do que qualquer outra coisa seria se mapeado para algo que você já conhecia, como linguagem comum, para começar com uma lacuna menor.

De qualquer forma, funcional e processual é um conceito bastante fluido e eles tendem a se sobrepor

Homde
fonte
4

Sim, a programação funcional tende a ser difícil de entender para muitas pessoas (eu diria, especialmente aquelas que já foram expostas à programação procedural).

Eu diria também que seu exemplo de programação funcional não é realmente um exemplo muito bom de programação funcional. Ele está usando recursão e apenas compondo um resultado em vez de modificar o estado, mas não muito mais do que isso.

Para obter um exemplo melhor de programação funcional, considere um problema mais geral: em vez de "procurar um sublinhado e converter a próxima letra em maiúscula", considere isso como apenas um caso especial de pesquisa de um padrão e execução de código arbitrário ao é encontrado.

Muitas linguagens suportam isso, mas para isso, elas exigem que especifiquemos o padrão como algo como uma expressão regular. Expressões regulares, no entanto, nada mais são do que uma linguagem de programação para fins especiais, e uma implementação de ER é um compilador e / ou intérprete para essa linguagem. O resultado da compilação do ER é basicamente uma função que é executada (em uma máquina virtual especial do RE) para corresponder a expressão a alguma entrada.

Em algo como Perl, você usa uma linguagem especial para especificar o padrão, e um compilador especial para converter essa string em algum tipo de função, e um intérprete especial para executar essa função. Em uma linguagem funcional, você normalmente usaria a própria linguagem para especificar o padrão e o compilador da própria linguagem para produzir uma função real . Podemos gerar essa função em tempo real (quase como podemos compilar um ER quando queremos), mas quando o fazemos, o resultado pode ser executado como qualquer outra função na linguagem, em vez de precisar de material RE especial para isso.

O resultado é que nós podemos generalizar o problema acima com relativa facilidade. Em vez de codificar o '_' e o "maiúsculo" diretamente na transformação, no entanto, podemos ter algo como:

s&r(pattern, transform, string) {
    if (!pattern(string))
        return string
    else
        return transform(matched part of string) + s&r(rest of string);
}

Mas, diferentemente de algo em que especificamos o padrão como um ER, podemos especificar o padrão diretamente como uma função real e ainda usá-lo, algo como:

my_pattern(string) return beginning(string) == '_';

E então passamos essa função para o s & r. No momento, é uma função bastante trivial, e a codificamos inteiramente estaticamente. Uma linguagem funcional se torna bastante interessante quando a usamos da maneira que podemos REs, e geramos uma função totalmente nova em tempo real com base em algo como a entrada do usuário, mas, diferentemente de uma RE, essa função não precisa de um intérprete RE especial para ser executado. apenas uma função normal como qualquer outra.

Jerry Coffin
fonte
4

Aqui está o código completo no Racket :

;; camelize : string -> string
(define (camelize str)
  (let ([parts (regexp-split #rx"_" str)])
    ;; result of regexp-split is never empty
    (apply string-append
           (first parts)
           (map string-titlecase (rest parts)))))

(camelize "qwe_asd_zxc_rty_fgh_vbn")
;; => "qweAsdZxcRtyFghVbn"

Como programador funcional com experiência processual, não acho que levaria mais tempo para "descobrir" uma solução processual, mas certamente levaria mais tempo para digitá-la.

BTW, o exemplo de resultado esperado na postagem original está errado: falta um "h" próximo ao final.

Ryan Culpepper
fonte
D'us por apontar isso. editada
Pacerier
3

Minha teoria do animal de estimação é que os modelos de programação são mais fáceis de entender quanto mais próximos eles estão do trabalho real dos computadores. Os ponteiros são difíceis de entender até que você perceba que eles são essencialmente endereços de máquinas. A recursão é difícil de entender até que você tenha percorrido conscientemente um pequeno exemplo, visto os quadros da pilha e percebido onde os diferentes valores da mesma variável são armazenados. Isso não significa que a programação do assembler seja mais fácil do que a programação de alto nível, mas ver como isso é feito faz maravilhas para o modelo mental que é essencial para a proficiência - seja na programação ou na usabilidade geral.

Agora, o modelo procedural está um pouco mais próximo da arquitetura usual da máquina: as atribuições são gravações na memória (ou registro). As chamadas de procedimento são realmente apenas saltos sofisticados, um ifsalto condicional etc. Mas no Lisp, por exemplo, não existe um nível simples equivalente a uma ligação lexical ou uma expressão lambda. Para entender isso, é necessário imaginar uma máquina funcional abstrata completamente separada entre o nível da linguagem e a máquina física, porque, aparentemente, a maioria das pessoas nunca chega tão longe.

( Estou familiarizado com a idéia de que a arquitetura de von Neumann é finalmente arbitrária, e não devemos prejudicar as mentes dos iniciantes com detalhes irrelevantes da arquitetura de máquinas e, em vez disso, apresentá-las diretamente à semântica das linguagens de programação. eu mesmo ministrei alguns desses cursos, mas cada vez mais sinto que esse é um objetivo nobre, porém equivocado; as pessoas aprendem a programar construindo o entendimento de baixo para cima, e o caminho para a programação funcional é simplesmente um pouco mais longo.)

Kilian Foth
fonte
7
Por essa lógica Assembler deve ser o mais fácil de todas as línguas para aprender :)
Homde
4
A programação funcional é bastante fácil de entender se você chegar na direção certa. A "máquina funcional abstrata" mencionada é simplesmente álgebra . A avaliação é feita por reescrita de termos; A aplicação da função é feita por substituição. Os programadores aprendem a resolver problemas usando as mesmas ferramentas que já viram em anos de aulas de matemática. Se eles perseguem CS, há tempo suficiente para encontrar a pilha de tartarugas mais tarde; caso contrário, eles ainda aprenderam habilidades úteis para a solução de problemas e princípios de design. Dê uma olhada em Como criar programas .
Ryan Culpepper
2
@ko Não, por essa lógica os bytecodes reais 011011001001101...seriam a linguagem mais fácil de aprender!
MarkJ
2
@ konrad: o montador RISC É provavelmente o idioma mais fácil de aprender. Saber como fazer algo útil é outra história totalmente ...
Bryan Boettcher