Eu apenas comecei a olhar para a reimplementação da biblioteca de coleções Scala, que está chegando na iminente versão 2.8 . Os familiarizados com a biblioteca da 2.7 perceberão que a biblioteca, da perspectiva do uso, mudou pouco. Por exemplo...
> List("Paris", "London").map(_.length)
res0: List[Int] List(5, 6)
... funcionaria em ambas as versões. A biblioteca é eminentemente útil : na verdade, é fantástica. No entanto, aqueles que antes não estavam familiarizados com o Scala e procuravam o idioma agora precisam entender as assinaturas de métodos como:
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That
Para uma funcionalidade tão simples, essa é uma assinatura assustadora e que me vejo lutando para entender. Não que eu ache que o Scala provavelmente seja o próximo Java (ou / C / C ++ / C #) - não acredito que seus criadores o tenham direcionado para esse mercado - mas acho que é / era certamente possível que o Scala se tornasse o próximo Ruby ou Python (ou seja, para obter uma base de usuários comercial significativa)
- Isso vai afastar as pessoas de virem para Scala?
- Isso vai dar a Scala um nome ruim no mundo comercial como um brinquedo acadêmico que apenas estudantes de doutorado dedicados podem entender? Os CTOs e chefes de software ficarão assustados?
- A biblioteca reprojetou uma ideia sensata?
- Se você estiver usando Scala comercialmente, está preocupado com isso? Você está planejando adotar o 2.8 imediatamente ou esperar para ver o que acontece?
Steve Yegge uma vez atacou Scala (erroneamente na minha opinião) pelo que ele viu como seu sistema de tipos super complicado. Eu me preocupo que alguém tenha um dia de campo divulgando o FUD com essa API (da mesma forma que Josh Bloch assustou o JCP ao adicionar closures ao Java).
Nota - Devo deixar claro que, embora acredite que Joshua Bloch tenha sido influente na rejeição da proposta de fechamento do BGGA, não atribuo isso a nada além de suas crenças honestas de que a proposta representou um erro.
Apesar do que minha esposa e colegas de trabalho continuam me dizendo, eu não acho que sou um idiota: tenho um bom diploma em matemática pela Universidade de Oxford e tenho programado comercialmente por quase 12 anos e em Scala por cerca de um ano (também comercialmente).
Observe que o título do assunto inflamatório é uma citação feita sobre o manifesto de um partido político do Reino Unido no início dos anos 80 . Esta pergunta é subjetiva, mas é uma pergunta genuína, eu a fiz como CW e gostaria de algumas opiniões sobre o assunto.
fonte
Respostas:
Espero que não seja uma "nota de suicídio", mas posso entender seu ponto de vista. Você encontra o que é ao mesmo tempo uma força e um problema de Scala: sua extensibilidade . Isso nos permite implementar a maioria das principais funcionalidades das bibliotecas. Em alguns outros idiomas, sequências com algo como
map
oucollect
seriam incorporadas, e ninguém precisa ver todos os obstáculos que o compilador precisa percorrer para fazê-los funcionar sem problemas. Em Scala, é tudo em uma biblioteca e, portanto, em campo aberto.De fato, a funcionalidade
map
suportada por seu tipo complicado é bastante avançada. Considere isto:Veja como você sempre obtém o melhor tipo possível? Se você mapear
Int
s paraInt
s, obterá novamente aBitSet
, mas se mapearInt
s paraString
s, obterá um generalSet
. O tipo estático e a representação em tempo de execução do resultado do mapa dependem do tipo de resultado da função que é passada para ele. E isso funciona mesmo que o conjunto esteja vazio, portanto a função nunca é aplicada! Tanto quanto eu sei, não há outra estrutura de coleta com uma funcionalidade equivalente. No entanto, da perspectiva do usuário, é assim que as coisas devem funcionar.O problema que temos é que toda a tecnologia inteligente que faz isso acontecer vaza para as assinaturas de tipo que se tornam grandes e assustadoras. Mas talvez um usuário não deva ser mostrado por padrão a assinatura de tipo completo
map
? Que tal se ela olhou para cimamap
,BitSet
ela conseguiu:Os documentos não estariam nesse caso, porque, na perspectiva do usuário, o mapa realmente tem o tipo
(Int => Int) => BitSet
. Masmap
também tem um tipo mais geral que pode ser inspecionado clicando em outro link.Ainda não implementamos funcionalidades como essas em nossas ferramentas. Mas acredito que precisamos fazer isso, para evitar assustar as pessoas e fornecer informações mais úteis. Com ferramentas como essa, espero que estruturas e bibliotecas inteligentes não se tornem notas de suicídio.
fonte
Não tenho doutorado, nem qualquer outro tipo de diploma nem em ciências da computação nem matemática, nem qualquer outro campo. Não tenho experiência anterior com Scala nem qualquer outro idioma semelhante. Não tenho experiência nem com sistemas remotamente comparáveis. De fato, a única linguagem que eu tenho mais do que apenas um conhecimento superficial do qual ainda possui um sistema de tipos é Pascal, não exatamente conhecido por seu sofisticado sistema de tipos. (Embora não têm tipos de gama, que AFAIK praticamente nenhuma outra língua tem, mas isso não é realmente relevante aqui.) As outras três línguas que eu conheço são BASIC, Smalltalk e Ruby, nenhum dos quais ainda têm um sistema do tipo.
E, no entanto, não tenho problemas para entender a assinatura da
map
função que você postou. Parece-me praticamente a mesma assinatura quemap
tem em todos os outros idiomas que eu já vi. A diferença é que esta versão é mais genérica. Parece mais uma coisa C ++ STL do que, digamos, Haskell. Em particular, ele abstrai do tipo de coleção concreta exigindo apenas que o argumento sejaIterableLike
, e também abstrai do tipo de retorno concreto exigindo apenas que exista uma função de conversão implícita que possa criar algo a partir dessa coleção de valores de resultados. Sim, isso é bastante complexo, mas na verdade é apenas uma expressão do paradigma geral da programação genérica: não assuma nada do que você realmente não precisa.Nesse caso,
map
na verdade , não é necessário que a coleção seja uma lista, ou seja ordenada ou ordenada ou algo parecido. A única coisa quemap
importa é que ele possa acessar todos os elementos da coleção, um após o outro, mas em nenhuma ordem específica. E ele não precisa saber qual é a coleção resultante, ela só precisa saber como construí-la. Então é isso que a assinatura do tipo requer.Então, ao invés de
que é a assinatura de tipo tradicional
map
, é generalizada para não exigir uma estrutura concreta,List
mas apenas umaIterableLike
estrutura de dadosque é generalizado ainda mais, exigindo apenas a existência de uma função que possa converter o resultado em qualquer estrutura de dados que o usuário desejar:
Admito que a sintaxe é um pouco mais desajeitada, mas a semântica é a mesma. Basicamente, começa a partir de
qual é a assinatura tradicional para
map
. (Observe como, devido à natureza orientada a objetos do Scala, o parâmetro da lista de entradas desaparece, porque agora é o parâmetro implícito do receptor que todo método em um sistema OO de despacho único possui.) Em seguida, generalizou de concretoList
para mais geralIterableLike
Agora, ele substitui a
IterableLike
coleção de resultados por uma função que produz , realmente, praticamente qualquer coisa.O que eu realmente acredito que não é tão difícil de entender. Na verdade, você precisa de apenas algumas ferramentas intelectuais:
map
é. Se você forneceu apenas a assinatura de tipo sem o nome do método, admito, seria muito mais difícil descobrir o que está acontecendo. Mas como você já sabe o quemap
deve fazer e sabe qual deve ser sua assinatura de tipo, pode digitalizar rapidamente a assinatura e se concentrar nas anomalias, como "por que issomap
leva duas funções como argumentos, não uma?"Nenhum desses três deve causar dor de cabeça a qualquer profissional ou programador amador.
map
tem sido uma função padrão em praticamente todas as linguagens projetadas nos últimos 50 anos, o fato de diferentes linguagens terem sintaxe diferente deve ser óbvio para quem criou um site com HTML e CSS e você não pode assinar uma programação nem remotamente lista de discussão relacionada sem algum fanboy irritante de C ++ da igreja de St. Stepanov, explicando as virtudes da programação genérica.Sim, Scala é complexo. Sim, o Scala possui um dos sistemas de tipos mais sofisticados conhecidos pelo homem, rivalizando e até superando idiomas como Haskell, Miranda, Clean ou Cyclone. Mas se a complexidade fosse um argumento contra o sucesso de uma linguagem de programação, o C ++ teria morrido há muito tempo e todos nós estaríamos escrevendo Scheme. Há muitas razões pelas quais o Scala provavelmente não será bem-sucedido, mas o fato de os programadores não se incomodarem em ligar o cérebro antes de se sentar na frente do teclado provavelmente não será o principal.
fonte
That
sendo inferido e vinculado ao tipoB
sendo uma pergunta que vem à mente. Onde estão os implícitos de ser outro. Mesmo sem essas observações detalhadas, ainda sinto pessoalmente que essa é uma assinatura complexa. Mas, evidentemente, existem pessoas como você por aí que não estão nem um pouco preocupadas com isso!A mesma coisa em C ++ :
fonte
func
deve ser um parâmetro de modelo e você deve usarresult_of
eis_callable
para obter outros tipos e restringir o conjunto sobrecarga apropriadamente :-)Bem, eu posso entender sua dor, mas, francamente, pessoas como você e eu - ou praticamente qualquer usuário comum do Stack Overflow - não são a regra.
O que quero dizer com isso é que ... a maioria dos programadores não liga para esse tipo de assinatura, porque nunca os verá ! Eles não leem a documentação.
Contanto que eles vissem algum exemplo de como o código funciona, e o código não os falha na produção do resultado esperado , eles nunca olharão para a documentação. Quando isso falha, eles analisam a documentação e esperam ver exemplos de uso na parte superior.
Com essas coisas em mente, acho que:
Qualquer pessoa (como a maioria das pessoas) que já se deparou com essa assinatura de tipo zombará de Scala sem fim, se estiver predisposta a ela, e considerará um símbolo do poder de Scala se gosta de Scala.
Se a documentação não for aprimorada para fornecer exemplos de uso e explicar claramente para que serve um método e como usá-lo, isso poderá prejudicar um pouco a adoção do Scala.
A longo prazo, isso não importa. Isso Scala pode fazer coisas como que vai fazer bibliotecas escritas para Scala muito mais poderoso e mais seguro para uso. Essas bibliotecas e estruturas atrairão programadores atraídos por ferramentas poderosas.
Os programadores que gostam de simplicidade e franqueza continuarão usando PHP ou linguagens semelhantes.
Infelizmente, os programadores de Java gostam muito de ferramentas elétricas; portanto, ao responder isso, acabei de revisar minha expectativa de adoção do Scala. Não tenho dúvidas de que Scala se tornará uma linguagem comum. Não C-mainstream, mas talvez Perl-mainstream ou PHP-mainstream.
Falando em Java, você já substituiu o carregador de classes? Você já olhou para o que isso envolve? Java pode ser assustador, se você observar os locais em que os escritores de estrutura fazem. É que a maioria das pessoas não. O mesmo se aplica a Scala, IMHO, mas os adotantes iniciais tendem a olhar embaixo de cada rocha que encontram, para ver se há algo escondido lá.
fonte
As long as they saw some example of how the code works, and the code doesn't fail them in producing the result they expect, they won't ever look at the documentation. When that fails, they'll look at the documentation and expect to see usage examples at the top.
Triste mas verdadeiro.Sim, mas também impedirá que as pessoas sejam adiadas. Eu considerei a falta de coleções que usam tipos de tipo superior como uma das principais fraquezas desde que o Scala ganhou suporte para tipos de tipo superior. Isso torna os documentos da API mais complicados, mas realmente torna o uso mais natural.
Alguns provavelmente o farão. Não acho que o Scala seja acessível a muitos desenvolvedores "profissionais", em parte devido à complexidade do Scala e em parte à falta de vontade de muitos desenvolvedores em aprender. Os CTOs que empregam esses desenvolvedores ficarão com medo.
Absolutamente. Faz com que as coleções se ajustem muito melhor ao restante do idioma e ao sistema de tipos, mesmo que ainda tenha algumas arestas.
Não estou usando comercialmente. Provavelmente esperarei até que pelo menos algumas pessoas entrem na série 2.8.x antes mesmo de tentar apresentá-la para que os erros possam ser eliminados. Também esperarei para ver quanto sucesso a EPFL tem em melhorar seu desenvolvimento e processos de lançamento. O que estou vendo parece esperançoso, mas trabalho para uma empresa conservadora.
Um dos tópicos mais gerais de "Scala é muito complicado para desenvolvedores comuns?" ...
A maioria dos desenvolvedores, mainstream ou não, mantém ou amplia os sistemas existentes. Isso significa que a maior parte do que eles usam é ditada por decisões tomadas há muito tempo. Ainda há muitas pessoas escrevendo COBOL.
O desenvolvedor principal de amanhã trabalhará na manutenção e ampliação dos aplicativos que estão sendo construídos hoje. Muitos desses aplicativos não estão sendo construídos por desenvolvedores convencionais. Os principais desenvolvedores de amanhã usarão a linguagem que está sendo usada pelos desenvolvedores mais bem-sucedidos de hoje de novos aplicativos.
fonte
Uma maneira pela qual a comunidade Scala pode ajudar a aliviar o medo de programadores novos no Scala é se concentrar na prática e ensinar com exemplos - muitos exemplos que começam pequenos e crescem gradualmente. Aqui estão alguns sites que adotam essa abordagem:
Depois de passar algum tempo nesses sites, percebe-se rapidamente que o Scala e suas bibliotecas, embora talvez sejam difíceis de projetar e implementar, não são tão difíceis de usar, especialmente nos casos comuns.
fonte
Eu tenho um diploma de graduação em uma universidade americana barata de "mercado de massa", então eu diria que caio no meio da escala de inteligência do usuário (ou pelo menos na educação) :) Estou brincando com o Scala há apenas alguns meses e trabalhou em dois ou três aplicativos não triviais.
Especialmente agora que o IntelliJ lançou seu excelente IDE com o que o IMHO atualmente é o melhor plugin do Scala, o desenvolvimento do Scala é relativamente simples:
Acho que posso usar o Scala como um "Java sem ponto e vírgula", ou seja, escrevo um código de aparência semelhante ao que eu faria em Java e me beneficio um pouco da brevidade sintática, como a obtida por inferência de tipo. O tratamento de exceções, quando eu faço isso, é mais conveniente. A definição de classe é muito menos detalhada sem o clichê getter / setter.
De vez em quando eu consigo escrever uma única linha para obter o equivalente a várias linhas de Java. Onde aplicável, cadeias de métodos funcionais como mapear, dobrar, coletar, filtrar etc. são divertidas de compor e elegantes de se ver.
Raramente me vejo beneficiando dos recursos mais poderosos do Scala: Fechos e funções parciais (ou curry), correspondência de padrões ... esse tipo de coisa.
Como iniciante, continuo lutando com a sintaxe concisa e idiomática. As chamadas de método sem parâmetros não precisam de parênteses, exceto onde precisam; os casos na instrução match precisam de uma seta grande (
=>
), mas também existem lugares em que você precisa de uma seta fina (->
). Muitos métodos têm nomes curtos, mas sim enigmáticas como/:
ou\:
- eu posso pegar minhas coisas feito se eu virar as páginas manuais suficientes, mas alguns dos meus fins de código acima de olhar como Perl ou ruído na linha. Ironicamente, um dos bits mais populares da abreviação sintática está faltando em ação: eu continuo sendo mordido pelo fato deInt
não definir um++
método.Esta é apenas a minha opinião: sinto que o Scala tem o poder do C ++ combinado com a complexidade e a legibilidade do C ++. A complexidade sintática da linguagem também dificulta a leitura da documentação da API.
Scala é muito bem pensado e brilhante em muitos aspectos. Eu suspeito que muitos acadêmicos adorariam programar nele. No entanto, também é cheio de esperteza e truques, possui uma curva de aprendizado muito maior que o Java e é mais difícil de ler. Se eu escanear os fóruns e ver quantos desenvolvedores ainda estão lutando com os pontos mais delicados do Java, não consigo conceber o Scala se tornando uma linguagem convencional . Nenhuma empresa poderá justificar o envio de seus desenvolvedores para um curso Scala de 3 semanas, quando antes eles precisavam apenas de um curso Java de 1 semana.
fonte
Eu acho que o principal problema com esse método é que o processo
(implicit bf : CanBuildFrom[Repr, B, That])
ocorre sem nenhuma explicação. Embora eu saiba o que são argumentos implícitos, não há nada indicando como isso afeta a chamada. Perseguir o scaladoc só me deixa mais confusa (poucas das classes relacionadasCanBuildFrom
ainda têm documentação).Eu acho que um simples "deve haver um objeto implícito no escopo,
bf
que forneça um construtor para objetos do tipoB
no tipo de retornoThat
" ajudaria um pouco, mas é um conceito inebriante quando tudo o que você realmente deseja fazer é mapearA
paraB
's. Na verdade, não tenho certeza se isso está certo, porque não sei o que o tipoRepr
significa, e a documentação paraTraversable
certamente não dá nenhuma pista.Então, eu tenho duas opções, nenhuma delas agradável:
Entendo que Scala está essencialmente expondo as entranhas de como essas coisas funcionam e que, em última análise, isso é uma maneira de fazer o que oxbow_lakes está descrevendo. Mas é uma distração na assinatura.
fonte
Repr
é a representação atravessável, ie.List
ouSet
ouMap
. Penso que, como estrutura, se você começar a examinar assinaturas de métodos (em vez de apenas usar os métodos copiando exemplos), deve entender primeiro o design geral. IMHO o Scaladoc deve estar cheio de exemplo de usoRepr
significava? Eu esperaria uma explicação no scaladoc, mas isso realmente não era óbvio para mim. Eu acho que esse é um padrão comum no scaladoc (vejaActor.react
eActor.receive
- disseram-me e vi que eles fazem coisas totalmente diferentes, mas o scaladoc é idêntico).Sou iniciante no Scala e, sinceramente, não vejo problemas com esse tipo de assinatura. O parâmetro é a função a ser mapeada e o parâmetro implícito no construtor para retornar a coleção correta. Claro e legível.
A coisa toda é bastante elegante, na verdade. Os parâmetros do tipo de construtor permitem que o compilador escolha o tipo de retorno correto, enquanto o mecanismo implícito de parâmetro oculta esse parâmetro extra do usuário da classe. Eu tentei isso:
Isso é polimorfismo feito da maneira certa.
Agora, concedido, não é um paradigma dominante e assustará muitos. Mas também atrairá muitos que valorizam sua expressividade e elegância.
fonte
Infelizmente, a assinatura do mapa que você forneceu é incorreta para o mapa e, de fato, há críticas legítimas.
A primeira crítica é que, subvertendo a assinatura do mapa, temos algo que é mais geral. É um erro comum acreditar que isso é uma virtude por padrão. Não é. A função map é muito bem definida como um functor covariável Fx -> (x -> y) -> Fy, com aderência às duas leis da composição e identidade. Qualquer outra coisa atribuída ao "mapa" é uma farsa.
A assinatura fornecida é outra coisa, mas não é um mapa. O que eu suspeito que está tentando ser é uma versão especializada e ligeiramente alterada da assinatura "transversal" do artigo, A Essência do Padrão Iterador. Aqui está a sua assinatura:
Vou convertê-lo para Scala:
Claro que falha - não é geral o suficiente! Além disso, é um pouco diferente (observe que você pode obter o mapa executando o deslocamento através do functor Identity). No entanto, suspeito que, se os escritores da biblioteca estivessem mais cientes das generalizações da biblioteca que estão bem documentadas (a Programação Aplicativa com Efeitos precede o mencionado), não veríamos esse erro.
Segundo, a função de mapa é um caso especial no Scala devido ao seu uso em for-compreende. Infelizmente, isso significa que um designer de biblioteca que está melhor equipado não pode ignorar esse erro sem sacrificar também o açúcar sintático das compreensões. Em outras palavras, se os designers da biblioteca Scala destruirem um método, isso será facilmente ignorado, mas não faça o mapeamento!
Espero que alguém fale sobre isso, porque, como está, será mais difícil solucionar os erros que Scala insiste em cometer, aparentemente por razões às quais tenho fortes objeções. Ou seja, a solução para "as objeções irresponsáveis do programador médio (ou seja, muito difícil!)" Não é "apaziguá-los para facilitar a tarefa", mas sim fornecer indicadores e assistência para se tornarem melhores programadores. Eu e os objetivos de Scala estamos em disputa sobre esse assunto, mas voltando ao seu ponto.
Você provavelmente estava fazendo o seu ponto, prevendo respostas específicas do "programador médio". Ou seja, as pessoas que reivindicarão "mas é muito complicado!" ou algo assim. Estes são os Yegges ou Blochs a que você se refere. Minha resposta a essas pessoas do movimento anti-intelectualismo / pragmatismo é bastante dura e eu já estou prevendo uma enxurrada de respostas, por isso vou omitir.
Eu realmente espero que as bibliotecas Scala melhorem, ou pelo menos, os erros possam ser guardados com segurança em um canto. Java é uma linguagem em que "tentar fazer algo útil" é tão incrivelmente caro que muitas vezes não vale a pena porque a enorme quantidade de erros simplesmente não pode ser evitada. Eu imploro a Scala que não siga o mesmo caminho.
fonte
Eu concordo totalmente com a pergunta e a resposta de Martin :). Mesmo em Java, a leitura de javadoc com genéricos é muito mais difícil do que deveria devido ao ruído extra. Isso é composto no Scala, onde parâmetros implícitos são usados como no código de exemplo das perguntas (enquanto os implícitos fazem coisas muito úteis para transformar a coleção).
Não acho que seja um problema com o idioma em si - acho que é mais uma questão de ferramentas. E, embora eu concorde com o que Jörg W Mittag diz, acho que olhar para o scaladoc (ou a documentação de um tipo no seu IDE) - deve exigir o mínimo de poder cerebral possível para entender o que é um método, o que é preciso e retorna. Não deve haver necessidade de cortar um pouco de álgebra em um pedaço de papel para obtê-lo :)
Certamente, os IDEs precisam de uma boa maneira de mostrar todos os métodos para qualquer variável / expressão / tipo (que, como no exemplo de Martin, pode incluir todos os genéricos incorporados, tornando-o agradável e fácil de entender). Também gosto da ideia de Martin de ocultar os implícitos.
Para dar o exemplo em scaladoc ...
Ao analisar isso no scaladoc, eu gostaria que o bloco genérico [B, That] estivesse oculto por padrão, bem como o parâmetro implícito (talvez eles sejam exibidos se você passar o mouse com um pequeno ícone) - como material extra para grok lendo, o que geralmente não é tão relevante. por exemplo, imagine se isso parecesse ...
agradável e claro e óbvio o que faz. Você pode se perguntar o que é 'Isso', se você clicar ou clicar nele, ele poderá expandir o texto [B, Isso], destacando o 'Isso', por exemplo.
Talvez um pequeno ícone possa ser usado para a declaração [] e o bloco (implícito ...), para que fique claro que existem pequenos pedaços da instrução recolhidos? É difícil usar um token para ele, mas eu usarei um. por enquanto...
Portanto, por padrão, o 'ruído' do sistema de tipos está oculto dos 80% principais do que as pessoas precisam examinar - o nome do método, seus tipos de parâmetros e seu tipo de retorno de maneira concisa simples e agradável - com pequenos links expansíveis para os detalhes se você realmente se importa tanto.
A maioria das pessoas está lendo o scaladoc para descobrir quais métodos eles podem chamar em um tipo e quais parâmetros eles podem passar. Estamos sobrecarregando os usuários com muitos detalhes, como IMHO.
Aqui está outro exemplo ...
Agora, se escondermos a declaração de genéricos, é mais fácil ler
Então, se as pessoas passarem o mouse sobre, digamos, A1, poderíamos mostrar a declaração de A1 como A1 <: A. Tipos covariantes e contravariantes em genéricos também acrescentam muito ruído, que pode ser renderizado de maneira muito mais fácil para os usuários que eu acho.
fonte
Não sei como explicar isso a você, mas tenho um doutorado em Cambridge e estou usando o 2.8 muito bem.
Mais seriamente, eu mal passei algum tempo com o 2.7 (ele não interage com a biblioteca Java que estou usando) e comecei a usar o Scala há pouco mais de um mês. Eu tenho alguma experiência com Haskell (não muito), mas simplesmente ignorei as coisas com as quais você está preocupado e procurei métodos que correspondessem à minha experiência com Java (que eu uso como meio de vida).
Então: eu sou um "novo usuário" e não fiquei desanimado - o fato de funcionar como Java me deu confiança suficiente para ignorar os bits que não entendi.
(No entanto, o motivo pelo qual eu estava olhando para o Scala foi em parte para ver se o empurra no trabalho, e ainda não o farei. Tornar a documentação menos intimidadora certamente ajudaria, mas o que me surpreendeu é o quanto ainda é mudando e sendo desenvolvido (para ser justo, o que mais me surpreendeu foi o quão impressionante é, mas as mudanças chegaram em um segundo próximo.) Então, acho que estou dizendo que prefiro que os recursos limitados sejam investidos um estado final - eu não acho que eles esperavam ser tão populares tão cedo.)
fonte
Não conheço Scala, no entanto, há algumas semanas atrás eu não conseguia ler Clojure. Agora eu posso ler a maioria, mas ainda não consigo escrever nada além dos exemplos mais simplistas . Suspeito que Scala não seja diferente. Você precisa de um bom livro ou curso, dependendo de como aprender. Apenas lendo a declaração do mapa acima, consegui talvez 1/3 dela.
Acredito que os problemas maiores não são a sintaxe dessas linguagens, mas a adoção e internalização dos paradigmas que os tornam utilizáveis no código de produção cotidiano. Para mim, o Java não foi um grande salto do C ++, que não foi um grande salto do C, que não foi um salto do Pascal, nem do Basic etc ... Mas codificar em uma linguagem funcional como o Clojure é um grande salto (por de qualquer maneira). Eu acho que no Scala você pode codificar no estilo Java ou no estilo Scala. Mas no Clojure você criará uma grande confusão tentando manter seus hábitos imperativos em Java.
fonte
O Scala tem muitos recursos malucos (principalmente no que diz respeito a parâmetros implícitos) que parecem muito complicados e acadêmicos, mas são projetados para facilitar as coisas. Os mais úteis obtêm açúcar sintático (como o
[A <% B]
que significa que um objeto do tipo A tem uma conversão implícita em um objeto do tipo B) e uma explicação bem documentada do que eles fazem. Mas na maioria das vezes, como cliente dessas bibliotecas, você pode ignorar os parâmetros implícitos e confiar neles para fazer a coisa certa.fonte
Eu não acho que seja o principal fator que afetará a popularidade do Scala, porque o Scala tem muito poder e sua sintaxe não é tão estranha para um programador Java / C ++ / PHP quanto Haskell, OCaml, SML, Lisps, etc ..
Mas acho que a popularidade do Scala alcançará um nível menor do que o Java hoje, porque também acho que a próxima linguagem mainstream deve ser muito simplificada, e a única maneira que vejo para chegar lá é pura imutabilidade, ou seja, declarativa como HTML, mas Turing completa . No entanto, sou tendencioso porque estou desenvolvendo essa linguagem, mas só o fiz depois de descartar um estudo de vários meses que Scala não seria suficiente para o que eu precisava.
Não acho que a reputação de Scala sofra com o complexo Haskell. Mas acho que alguns adiarão o aprendizado, porque para a maioria dos programadores, ainda não vejo um caso de uso que os obriga a usar o Scala, e eles vão adiar o aprendizado sobre ele. Talvez o lado do servidor altamente escalável seja o caso de uso mais atraente.
E, para o mercado convencional, o primeiro aprendizado do Scala não é uma "lufada de ar fresco", onde se escreve programas imediatamente, como o primeiro a usar HTML ou Python. Scala tende a crescer em você, depois de aprender todos os detalhes em que se encontra desde o início. No entanto, talvez se eu tivesse lido Programação em Scala desde o início, minha experiência e opinião sobre a curva de aprendizado teriam sido diferentes.
Definitivamente.
Estou usando o Scala como plataforma inicial do meu novo idioma. Provavelmente, eu não estaria criando código na biblioteca de coleções do Scala se estivesse usando o Scala comercialmente. Eu criaria minha própria biblioteca baseada em teoria de categorias, desde a primeira vez que encontrei, achei as assinaturas de tipo de Scalaz ainda mais detalhadas e difíceis de manusear do que a biblioteca de coleções de Scala. Parte desse problema talvez seja a maneira como Scala implementa classes de tipos, e esse é um motivo menor pelo qual estou criando minha própria linguagem.
Decidi escrever essa resposta, porque queria me forçar a pesquisar e comparar o design da classe de coleção do Scala com o que estou fazendo no meu idioma. Pode muito bem compartilhar meu processo de pensamento.
O uso de uma abstração de construtor das coleções Scala 2.8 é um princípio de design sólido. Quero explorar duas vantagens e desvantagens do design abaixo.
CÓDIGO DE GRAVAÇÃO: Depois de escrever esta seção, li o comentário de Carl Smotricz que concorda com o que espero ser a troca. Os comentários de James Strachan e davetron5000 concordam que o significado de Isso (nem mesmo é isso [B]) e o mecanismo do implícito não são fáceis de entender intuitivamente. Veja meu uso do monóide na edição 2 abaixo, que eu acho muito mais explícita. O comentário de Derek Mahar é sobre escrever Scala, mas que tal ler o Scala de outros que não está "nos casos comuns".
Uma crítica que li sobre Scala é que é mais fácil escrevê-lo do que ler o código que outros escreveram. E acho que isso ocasionalmente é verdade por várias razões (por exemplo, várias maneiras de escrever uma função, fechamentos automáticos, unidade para DSLs, etc.), mas não sei se esse é o principal fator. Aqui, o uso de parâmetros de função implícitos possui vantagens e desvantagens. No lado positivo, reduz a verbosidade e automatiza a seleção do objeto do construtor. Na casa de Odersky exemploa conversão de um BitSet, ou seja, Set [Int], para um Set [String] está implícita. O leitor desconhecido do código pode não saber prontamente qual é o tipo de coleção, a menos que possa raciocinar bem sobre todos os possíveis candidatos a construtores implícitos invisíveis que possam existir no escopo do pacote atual. Obviamente, o programador experiente e o escritor do código saberão que o BitSet é limitado a Int, portanto, um mapa para String precisa ser convertido em um tipo de coleção diferente. Mas que tipo de coleção? Não está especificado explicitamente.
DESIGN DA COLEÇÃO AD-HOC: Depois de escrever esta seção, li o comentário de Tony Morris e percebi que estou fazendo quase o mesmo ponto. Talvez minha exposição mais detalhada torne o argumento mais claro.
Em "Combate à podridão de bits com tipos" Odersky & Moors, dois casos de uso são apresentados. Eles são a restrição dos elementos BitSet para Int e Map para emparelhar elementos de tupla, e são fornecidos como o motivo pelo qual a função de mapeamento de elemento geral, A => B, deve ser capaz de criar tipos alternativos de coleta de destino. No entanto, apesar de tudo isso é defeituoso do ponto de vista da teoria das categorias. Para ser consistente na teoria das categorias e, assim, evitar casos de canto, esses tipos de coleção são functors, nos quais cada morfismo, A => B, deve mapear entre objetos na mesma categoria de functor, List [A] => List [B], BitSet [A] => BitSet [B]. Por exemplo, uma opção é um functor que pode ser visto como uma coleção de conjuntos de um Some (objeto) e o None. Não existe um mapa geral de None da Option, ou List's Nil, para outros functores que não
Há uma escolha de design de troca feita aqui. Na biblioteca de design para coleções da minha nova linguagem, optei por transformar tudo em um functor, o que significa que, se eu implementar um BitSet, ele precisará suportar todos os tipos de elementos, usando uma representação interna de campo que não seja um bit, quando apresentada com um nome não- parâmetro de tipo inteiro e essa funcionalidade já está no conjunto do qual ele é herdado no Scala. E Map no meu design precisa mapear apenas seus valores, e ele pode fornecer um método não-functor separado para mapear suas tuplas de pares (chave, valor). Uma vantagem é que cada função é geralmente também um aplicativo e talvez uma mônada também. Assim, todas as funções entre os tipos de elementos, por exemplo, A => B => C => D => ..., são automaticamente levantadas para as funções entre os tipos de aplicativos levantados, por exemplo, Lista [A] => Lista [B] => Lista [ C] => Lista [D] => .... Para mapear de um functor para outra classe de coleção, ofereço uma sobrecarga de mapa que utiliza um monóide, por exemplo, Nil, Nenhum, 0, "", Array (), etc.) Portanto, a função de abstração do construtor é o método de acréscimo de um monóide e é fornecido explicitamente como um parâmetro de entrada necessário, portanto, sem conversões implícitas invisíveis. (Tangente: esse parâmetro de entrada também permite acrescentar monoides não vazios, o que o design do mapa de Scala não pode fazer.) Essas conversões são um mapa e uma dobra na mesma passagem de iteração. Também forneço um McBride & Patterson que pode ser percorrido, no sentido de categoria, "Programação Aplicativa com Efeitos", que também permite map + fold em uma única passagem de iteração de qualquer passável para qualquer aplicativo, onde quase todas as classes de coleção são ambas.
Tão afaics que as coleções Scala são "ad-hoc" no sentido de que não se fundamentam na teoria das categorias, e a teoria das categorias é a essência da semântica denotacional de nível superior. Embora os construtores implícitos de Scala sejam, à primeira vista, "mais generalizados" do que um modelo de functor + construtor monóide + aplicável atravessável ->, eles não são comprovadamente consistentes com nenhuma categoria e, portanto, não sabemos quais regras eles seguem no No sentido mais geral e como serão apresentados os casos de canto, eles podem não obedecer a nenhum modelo de categoria. Simplesmente não é verdade que adicionar mais variáveis torne algo mais geral, e esse foi um dos grandes benefícios da teoria das categorias: ela fornece regras pelas quais manter a generalidade enquanto se eleva para a semântica de nível superior. Uma coleção é uma categoria.
Li em algum lugar, acho que foi Odersky, como outra justificativa para o design da biblioteca, é que a programação em um estilo funcional puro tem o custo de recursão e velocidade limitadas, onde a recursão de cauda não é usada. Não achei difícil empregar recursão de cauda em todos os casos que encontrei até agora.
Além disso, tenho em mente uma ideia incompleta de que algumas das compensações de Scala se devem a tentar ser uma linguagem mutável e imutável, diferente de, por exemplo, Haskell ou a linguagem que estou desenvolvendo. Isso concorda com o comentário de Tony Morris sobre compreensão. No meu idioma, não há loops nem construções mutáveis. Meu idioma ficará no topo do Scala (por enquanto) e deve muito a ele, e isso não seria possível se o Scala não tivesse o sistema de tipo geral e a mutabilidade. Isso pode não ser verdade, porque acho que a Odersky & Moors ("Fighting Bit Rot with Types") está incorreta ao afirmar que Scala é a única linguagem OOP com tipos mais altos, porque verifiquei (eu e via Bob Harper) esse padrão ML os tem. Também parece que o sistema de tipos do SML pode ser equivalente a flexível (desde os anos 80), o que pode não ser facilmente apreciado porque a sintaxe não é tão semelhante ao Java (e C ++ / PHP) quanto o Scala. De qualquer forma, isso não é uma crítica a Scala, mas sim uma tentativa de apresentar uma análise incompleta das compensações, que espero que seja pertinente à questão. Scala e SML não sofrem com a incapacidade de Haskell de fazerherança múltipla de diamantes , o que é fundamental e eu entendo por que tantas funções no Haskell Prelude são repetidas para diferentes tipos.
fonte
Parece necessário declarar um diploma aqui: bacharelado em ciência política e bacharelado em ciência da computação.
Ao ponto:
Scala é difícil, porque seu paradigma de programação subjacente é difícil. A programação funcional assusta muitas pessoas. É possível criar fechamentos em PHP, mas as pessoas raramente o fazem. Portanto, não, não essa assinatura, mas todo o resto adiará as pessoas, se elas não tiverem a educação específica para fazê-las valorizar o poder do paradigma subjacente.
Se essa educação estiver disponível, todos poderão fazê-lo. No ano passado, construí um computador de xadrez com um monte de crianças da escola em SCALA! Eles tiveram seus problemas, mas acabaram bem no final.
Eu não ficaria preocupado.
fonte
Eu também tenho um diploma de matemática em Oxford! Levei um tempo para 'pegar' o material das novas coleções. Mas eu gosto muito agora que gosto. De fato, a digitação de 'mapa' foi uma das primeiras grandes coisas que me incomodaram em 2.7 (talvez desde que a primeira coisa que fiz foi subclasse uma das classes de coleção).
Ler o artigo de Martin sobre as novas coleções 2.8 realmente ajudou a explicar o uso de implícitos, mas sim, a documentação em si definitivamente precisa fazer um trabalho melhor de explicar o papel de diferentes tipos de implícitos nas assinaturas de métodos das principais APIs.
Minha principal preocupação é mais: quando o 2.8 será lançado? Quando os relatórios de erros deixarão de aparecer? a equipe do scala se saiu mais do que consegue mastigar com 2.8 / tentou mudar muito de uma só vez?
Eu realmente gostaria de ver o 2.8 estabilizado para lançamento como uma prioridade antes de adicionar qualquer outra novidade, e me pergunto (enquanto observava à margem) se algumas melhorias poderiam ser feitas na maneira como o roteiro de desenvolvimento para o compilador scala é gerenciado.
fonte
E as mensagens de erro no site em uso?
E quando chega o caso de uso necessário para integrar os tipos existentes com um personalizado que se encaixa em uma DSL. É preciso ser bem educado em questões de associação, precedência, conversões implícitas, parâmetros implícitos, tipos superiores e talvez tipos existenciais.
É muito bom saber que a maioria é simples, mas não é necessariamente suficiente. Pelo menos, deve haver um cara que conheça essas coisas para que uma ampla biblioteca seja projetada.
fonte