A biblioteca de coleções do Scala 2.8 é um caso de “a maior nota de suicídio da história”? [fechadas]


873

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.


10
fud apenas significa medo, incerteza e dúvida - acho que expressa claramente o tom da palestra de Josh Bloch, que eu também concordo que é bem argumentada e fundamentada, etc. Se você vê as edições, não coloquei fud originalmente porque Eu não queria implicar conotações ve
oxbow_lakes

32
Esta questão foi mencionada na palestra de abertura de Martin Odersky no Scala Days 2010 days2010.scala-lang.org/node/136
Binil Thomas

7
O que eu amo no Scala é que você não precisa entender que é um sistema de tipos complexo para fazer coisas simples e elegantes. sua sintaxe pode ser assustadora, mas garante uma coisa: não há "mágica", por exemplo, a magia faz parte da linguagem, é uma abordagem muito corajosa e inteligente, acho que você tem uma linguagem que pode criar novas DSLs e novas mini línguas dentro de si, sim, com as mãos erradas Scala pode ser um excelente complemento para o seu jantar italiano, mas uma vez que você se acostumar com isso, é uma linguagem incrível
Eran Medan

87
Como essa pergunta pode ser "não construtiva" quando levou a @MartinOdersky a reavaliar a usabilidade do Scala e tornar seu sistema de documentação ocultar os detalhes do sistema, sem mencionar uma discussão esclarecedora?
precisa saber é o seguinte

14
De fato, o SO é apenas por tecnicidade com o formato certo. Se você tem algo delicado, intrigante e abrangente, procure outro lugar. Viva a mentalidade burocrática.
qed

Respostas:


892

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 mapou collectseriam 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 mapsuportada por seu tipo complicado é bastante avançada. Considere isto:

scala> import collection.immutable.BitSet
import collection.immutable.BitSet

scala> val bits = BitSet(1, 2, 3)
bits: scala.collection.immutable.BitSet = BitSet(1, 2, 3)

scala> val shifted = bits map { _ + 1 }
shifted: scala.collection.immutable.BitSet = BitSet(2, 3, 4)

scala> val displayed = bits map { _.toString + "!" }
displayed: scala.collection.immutable.Set[java.lang.String] = Set(1!, 2!, 3!)

Veja como você sempre obtém o melhor tipo possível? Se você mapear Ints para Ints, obterá novamente a BitSet, mas se mapear Ints para Strings, obterá um general Set. 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 cima map, BitSetela conseguiu:

map(f: Int => Int): BitSet     (click here for more general type)

Os documentos não estariam nesse caso, porque, na perspectiva do usuário, o mapa realmente tem o tipo (Int => Int) => BitSet. Mas maptambé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.


107
Eu me sinto como um estudante travesso! Muito obrigado por responder aqui. Eu acho que o balanço de respostas me mostrou que não preciso me preocupar; haverá muitas pessoas que não se intimidarão.
Oxbow_lakes 13/11/2009

164
Não, acho que você estava absolutamente certo em acertar nesse ponto. E outras pessoas terão medo, a menos que façamos algo a respeito.
Martin Odersky

33
Martin, eu gosto da sua sugestão para mostrar assinaturas de um método simplificado e ocultar os detalhes gerais atrás de um link.
Derek Mahar

18
Eu acho que uma solução que funcionaria pelo menos também é mais explicações nos documentos. Eu não consideraria as assinaturas tão intimidadoras, se não fosse pelo fato de a maioria dos métodos (e até a maioria das classes) não terem mais do que uma frase descrevendo seu objetivo e operação.
Nick Johnson

98
Atualização: A versão final do Scala 2.8 possui um mecanismo como o que eu descrevi. Se você procurar o BitSet nos escaladocs, encontrará: def map [B] (f: (Int) ⇒ B): BitSet [B] [caso de uso] Constrói uma nova coleção aplicando uma função a todos os elementos desse conjunto de bits.
Martin Odersky

226

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 mapfunção que você postou. Parece-me praticamente a mesma assinatura que maptem 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 seja IterableLike, 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, mapna verdade , não é necessário que a coleção seja uma lista, ou seja ordenada ou ordenada ou algo parecido. A única coisa que mapimporta é 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

map :: (a → b)[a][b]

que é a assinatura de tipo tradicional map, é generalizada para não exigir uma estrutura concreta, Listmas apenas uma IterableLikeestrutura de dados

map :: (IterableLike i, IterableLike j)(a → b) → i → j

que é 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:

map :: IterableLike i ⇒ (a → b) → i → ([b] → c) → c

Admito que a sintaxe é um pouco mais desajeitada, mas a semântica é a mesma. Basicamente, começa a partir de

def map[B](f: (A) ⇒ B): List[B]

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 concreto Listpara mais geralIterableLike

def map[B](f: (A) ⇒ B): IterableLike[B]

Agora, ele substitui a IterableLikecoleção de resultados por uma função que produz , realmente, praticamente qualquer coisa.

def map[B, That](f: A ⇒ B)(implicit bf: CanBuildFrom[Repr, B, That]): That

O que eu realmente acredito que não é tão difícil de entender. Na verdade, você precisa de apenas algumas ferramentas intelectuais:

  1. Você precisa saber (aproximadamente) o que 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 que mapdeve fazer e sabe qual deve ser sua assinatura de tipo, pode digitalizar rapidamente a assinatura e se concentrar nas anomalias, como "por que isso mapleva duas funções como argumentos, não uma?"
  2. Você precisa realmente ler a assinatura de tipo. Mas mesmo que você nunca tenha visto o Scala antes, isso deve ser bastante fácil, pois é realmente apenas uma mistura de sintaxes de tipo que você já conhece de outros idiomas: o VB.NET usa colchetes para polimorfismo paramétrico e usa uma seta para indicar o tipo de retorno e dois pontos para separar nome e tipo, é realmente a norma.
  3. Você precisa saber aproximadamente do que trata a programação genérica. (O que não é tão difícil de entender, já que está basicamente escrito em nome: é literalmente apenas programação de maneira genérica).

Nenhum desses três deve causar dor de cabeça a qualquer profissional ou programador amador. maptem 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.


36
@ Jorg - essa é uma resposta incrível; obrigado. Se você tem um diploma ou não, você é um homem mais inteligente do que eu. A única queixa que tenho é que compreendo o panorama geral do que está acontecendo na assinatura do método. No entanto, os detalhes ainda são confusos: como está Thatsendo inferido e vinculado ao tipo Bsendo 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!
Oxbow_lakes 12/11/2009

50
Boa explicação, mas você me convenceu ainda mais de que a assinatura do método Scala 2.8 "map" é muito complicada.
Derek Mahar

11
Uma linguagem que se parece com isso: def map [B] (f: (A) ⇒ B): IterableLike [B] é muito mais convidativa do que uma que se parece com isso: def map [B, que] (f: A ⇒ B ) (implícito bf: CanBuildFrom [Repr, B, That]): Isso
Mark Essel 03/04

215
Acho interessante que você comece afirmando conhecer apenas básico, ruby ​​e smalltalk, e continuando que não possui formação acadêmica no assunto. ... e depois reivindicando conhecimento sobre a complexidade dos sistemas de tipos em linguagens como Miranda e Clean; linguagens conhecidas principalmente entre linguistas de programação sérios, geeks e acadêmicos.
Sami

14
Você tem um ponto válido de que a comparação com Haskell está incorreta, pois "map :: (a -> b) -> [a] -> [b]" é específico para Listas. No entanto, a versão generalizada, o da classe Functor, ainda é muito mais simples do que a Scala versão: class Functor f onde fmap :: (a -> b) -> fa -> fb
Orclev

175

A mesma coisa em C ++ :

template <template <class, class> class C,
          class T,
          class A,
          class T_return,
          class T_arg
              >
C<T_return, typename A::rebind<T_return>::other>
map(C<T, A> &c,T_return(*func)(T_arg) )
{
    C<T_return, typename A::rebind<T_return>::other> res;
    for ( C<T,A>::iterator it=c.begin() ; it != c.end(); it++ ){
        res.push_back(func(*it));
    }
    return res;
}

105
... e eles dizem que Scala é obscuro. Duh!
missingfaktor

24
Imagine como teria sido se identificadores autoexplicativos adequados tivessem sido usados ​​em vez de letras maiúsculas arbitrárias. :-)
Ti Strga

14
É útil ver essa comparação, mas seria mais justo se a implementação fosse omitida.
Aaron Novstrup 20/09/2013

2
Eu não sou um grande fã do ponteiro de função obrigatório. Claramente, o tipo de funcdeve ser um parâmetro de modelo e você deve usar result_ofeis_callable para obter outros tipos e restringir o conjunto sobrecarga apropriadamente :-)
Kerrek SB

1
meus olhos doem !!!
Ashkan Kh. Nazary

71

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:

  1. 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.

  2. 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.

  3. 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.

  4. 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á.


10
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.
gamliela

9
@ Pamliela, não acho que ficaremos tristes com isso. O conhecimento sempre tem mais de um nível para aplicar, e o trabalho e a confiança dos outros (revisados ​​por pares) em qualquer sistema sempre podem ser aproveitados, assim como usamos aritmética diariamente e ignora totalmente as álgebras assustadoras que trabalham por trás dele.
Lcn 06/12/19

55

Isso vai afastar as pessoas de virem para Scala?

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.

Isso dará a scala um nome ruim no mundo comercial como um brinquedo acadêmico que apenas estudantes de doutorado dedicados podem entender? CTOs e chefes de software vão se assustar?

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.

A biblioteca reprojetou uma ideia sensata?

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.

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?

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.


31
"também impedirá que as pessoas sejam adiadas". isto. absolutamente. O scala é a primeira linguagem que torna a engenharia com algo comparável ao haskell (no poder de seu sistema de tipos) uma possibilidade para muitos de nós. não há nenhuma maneira idiota de convencer o trabalho a usar o haskell, mas a scala realmente tem uma chance e por isso eu a amo e tentarei (quando achar que faz sentido) tentar adotá-la, ou pelo menos ser aceita, no trabalho.
andrew cooke

+1 de mim também. Dada a premissa de que Scala coloca mais ênfase na profundidade e no rigor lingüístico do que na acessibilidade em massa, essas respostas se encaixam perfeitamente.
12249 Carl Smotricz

16
"Os principais desenvolvedores de amanhã usarão a linguagem que está sendo usada pelos desenvolvedores mais bem-sucedidos de hoje de novos aplicativos". +1. Brilhantemente disse.
Vasil Remeniuk

46

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.


43

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 de Intnã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.


9
Desculpe por todos os comentários. Uma semana é uma piada para praticamente qualquer idioma, mas isso não impede que os gerentes ponham em prática essa piada. Certa vez, recebi três dias para "treinar" um grupo de desenvolvedores de C ++ em Java. Pedi 5 dias, mas fui interrompido por razões de orçamento.
12139 Carl Smotricz

22
No meu primeiro emprego, recebi um livro em C ++ no final da entrevista para aprender antes de começar a trabalhar na segunda-feira. Vocês são todos covardes.
Tom Hawtin - tackline

12
@ Tom @ Erik Vocês, rapazes, têm facilidade. Foi-me dado os diagramas de circuitos para o computador (nenhuma parte traseira CPU então), e disse que eu tinha duas horas para corrigir um bug como a entrevista.
2213 Daniel C. Sobral

33
@Daniel @Tom @Erik Recebi um 0 e um 1 e pedi para usá-los para resolver o problema da mochila em tempo linear durante a entrevista. Eu tentei, mas infelizmente só tive tempo para criar o Eclipse (que eu suspeito que possa ser redutível em mochila). #all_tale
Alex Miller

10
@ Alex Isso mostra falta de imaginação. Coloque um zero grande à esquerda e dois outros zeros menores à direita: um acima do outro, o superior levemente à esquerda. Coloque aquele entre esses dois zeros menores, indo da parte inferior esquerda para a parte superior direita. Digamos que essa é a chance de resolver a mochila em tempo linear. Pronto, pronto. :-) +1 por igualar Eclipse e Mochila, no entanto. :-)
Daniel C. Sobral

33

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 relacionadas CanBuildFromainda têm documentação).

Eu acho que um simples "deve haver um objeto implícito no escopo, bfque forneça um construtor para objetos do tipo Bno tipo de retorno That" ajudaria um pouco, mas é um conceito inebriante quando tudo o que você realmente deseja fazer é mapear Apara B's. Na verdade, não tenho certeza se isso está certo, porque não sei o que o tipo Reprsignifica, e a documentação para Traversablecertamente não dá nenhuma pista.

Então, eu tenho duas opções, nenhuma delas agradável:

  • Suponha que funcione apenas como o mapa antigo funciona e como o mapa funciona na maioria dos outros idiomas
  • Pesquise o código-fonte um pouco mais

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.


2
Repré a representação atravessável, ie. Listou Setou Map. 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 uso
oxbow_lakes

10
Então, como eu determinaria o que Reprsignificava? 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 (veja Actor.reacte Actor.receive- disseram-me e vi que eles fazem coisas totalmente diferentes, mas o scaladoc é idêntico).
Davetron5000 /

7
Eu concordo com davetron5000. Estou familiarizado com Scala, mas as definições implícitas ainda fazem minha cabeça doer. E o motivo não está implícito per se, mas como eles são usados. Definitivamente deve haver melhor documentação e suporte de ferramentas para entender os tipos de Scala. Dito isto, acho que o sistema de tipos realmente tem algo importante a oferecer. Mas ainda estamos apenas no começo do caminho da programação sensível.
egaga 28/03

22

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:

Map(1 -> "a", 2 -> "b").map((t) => (t._2) -> (t._1)) // returns Map("a" -> 1, "b" -> 2)
Map(1 -> "a", 2 -> "b").map((t) =>  t._2)            // returns List("a", "b")

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.


20

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:

traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)

Vou convertê-lo para Scala:

def traverse[A, B](f: A => F[B], a: T[A])(implicit t: Traversable[T], ap: Applicative[F]): F[T[B]

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.


3
Oi Tony - obrigado por sua contribuição atenciosa aqui. Eu daria 2 respostas a ele. A primeira é que não mencionei o "programador médio" e não acredito que o Scala seja necessariamente destinado a um. Seja vaidoso ou não, acredito que estou acima da média; no entanto, ainda sinto que a assinatura de tipo é assustadora! Ainda me preocupo, em outras palavras, que programadores acima da média, o mercado-alvo da Scala, possam ser afastados.
Oxbow_lakes 15/11/2009

6
O segundo ponto é que eu discordo fundamentalmente de você sobre o que é Scala: Scala é uma linguagem pragmática - não uma teoricamente pura. Por que outro motivo teria sido projetado no topo da JVM? Esta é uma decisão puramente pragmática - está sendo direcionada aos desenvolvedores "no mundo real" - uma escolha que pode ter exigido compromissos! Observe também que Bloch e Yegge estão longe da média dos programadores - mas esse é o meu ponto. Mesmo pessoas altamente respeitadas e inteligentes podem ter opiniões sobre complexidade e pureza diferentes da sua. Infelizmente para você, eles também são altamente influentes.
Oxbow_lakes 15/11/2009

3
Olá oxbow_lakes, É um objetivo declarado do Scala apaziguar programadores típicos, mesmo à custa da precisão e praticidade. Programadores acima da média são expulsos (tenho várias histórias), mas não porque as assinaturas de tipo são assustadoras, mas devido à natureza de alguns dos erros. Eu não disse que Scala é ou não é pragmático ou teórico. Além disso, eu nem subscrevo a ideia (comum?) De que essa dicotomia existe. As bibliotecas Scala estragaram a assinatura do mapa. Eu tenho trabalhado com os erros de Scala há anos; particularmente as bibliotecas. Hora de fazê-lo novamente.
21813 Tony Morris

5
Não considero Bloch ou Yegge altamente respeitados ou inteligentes, mas eles são realmente bastante influentes. Sim, isso é lamentável.
22813 Tony Morris

9
Por que você se relaciona com a assinatura estendida do Scala? O mapa de Scala, para monofuncionais, é o fmap padrão. Mas nem o BitSet nem o Mapa [A, B] são monofuncionais, mas o mapa possui uma definição significativa. Essa é a motivação da assinatura de Scala, e a travessia não resolve esse problema. Por que a generalidade é uma coisa ruim? Os functores aplicáveis ​​acompanham os efeitos, qual é o objetivo deles em Scala? Finalmente, acredito que o mapa genérico de Scala pode ser implementado em termos de uma travessia generalizada, aceitando um CanBuildFrom e retornando um Traversable potencialmente diferente: não há necessidade de sacrificar a compreensão!
Blaisorblade 30/03

15

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 ...

def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That

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 ...

def map(f: A => B): That

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...

def map.(f: A => B).: That

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 ...

def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]): PartialFunction[A1, B1]

Agora, se escondermos a declaração de genéricos, é mais fácil ler

def orElse(that: PartialFunction[A1, B1]): PartialFunction[A1, B1]

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.


5
Mas o que "Isso" significa como tipo de resultado?
Blaisorblade 30/03

11

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.)


22
Acho que ele quer saber se pessoas sem PhD em Cambridge podem lidar com o Scala 2.8.
Ken Bloom

2
Haha: touche! Bem, eu disse que o scala 2.8 é fácil de usar - minha pergunta era mais sobre como seria alguém navegar na API para ver se gostava, assumindo que não tinha experiência anterior no Scala.
Oxbow_lakes 12/11/2009

1
@ Andrew - a partir da aparência yout website ( acooke.org ), você não está desconfortável com conceitos visualmente intimidante
oxbow_lakes

Qualquer pessoa ocupada com a programação de Malbolge, mesmo que seja "apenas" Hello World, provavelmente não ficará intimidada com nada.
12249 Carl Smotricz

10

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.


5
Nunca se trata de notação (ou nunca mais do que, digamos, 10 a 15% sobre notação), é sempre sobre conceitos. E se você é razoavelmente inteligente e não está atolado em décadas de conhecimento de modelos diferentes e possivelmente contraditórios (como eu provavelmente sou), então geralmente não é muito difícil entender essas coisas. Mas se você está imerso em uma maneira de pensar e fazer as coisas, então há pelo menos algum esforço para se adaptar e muitos reagem a essas mudanças. É apenas a psicologia humana / natureza. (Eu me pergunto como Psychology of Computer Programming de Weinberg mantém-se depois de quase 40 anos?)
Randall Schulz

1
@ Randall Schultz e Jeff G: Sintaxe / notação é razoavelmente fácil para uma pessoa inteligente lidar. Nomes diferentes para os mesmos conceitos, basicamente. Acelerar em um novo idioma é apenas uma questão de prática. NO ENTANTO, o passo da programação processual para a funcional é ... assustadoramente amplo. É realmente uma maneira diferente de pensar. Estou brincando com o Clojure há alguns meses e acho uma linguagem FP relativamente agradável e fácil. Mas ainda preciso de quantidades excessivas de tempo para entender coisas que seriam diretas na programação processual.
Carl Smotricz 29/03/10

7

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.


Sim, a sintaxe da visualização torna as coisas mais rápidas de entender.
egaga 28/03

6

Isso vai afastar as pessoas de virem para Scala?

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.

Isso vai dar a Scala um nome ruim no mundo comercial como um brinquedo acadêmico que apenas estudantes de doutorado dedicados podem entender? CTOs e chefes de software vão se assustar?

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.

A biblioteca reprojetou uma ideia sensata?

Definitivamente.

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?

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.

  1. 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.

  2. 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.


Então, sua linguagem será orientada a objetos?
missingfaktor

Sim, herda o sistema de tipos do Scala. Uma distinção chave é que o traço é dividido em interface e mixin, em que a interface contém apenas assinaturas de métodos e nenhuma implementação. E apenas uma interface pode ser referenciada como um tipo. Os implícitos são eliminados e as classes de tipo são tratadas de maneira SPOT na interface. Aqui está um rascunho de detalhes. Colaboradores são bem-vindos. Algum código para a biblioteca está aqui . Este é um trabalho em andamento, desculpas por mencionar o vaporware. Apenas compartilhando pensamentos.
Shelby Moore III

5

Parece necessário declarar um diploma aqui: bacharelado em ciência política e bacharelado em ciência da computação.

Ao ponto:

Isso vai afastar as pessoas de virem para Scala?

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.

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?

Eu não ficaria preocupado.


4

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.


-1

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.


Mas um dos pontos principais é a diferença entre a biblioteca da perspectiva de um usuário e os criadores. Obviamente, os criadores precisam de uma compreensão impressionante dos recursos de linguagem necessários (por exemplo, tipos mais altos, precedência implícita) - a pergunta é: "os usuários precisam?"
oxbow_lakes
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.