Acabo de comenzar a mirar la reimplementación de la biblioteca de colecciones Scala que viene en la inminente versión 2.8 . Aquellos familiarizados con la biblioteca de 2.7 notarán que la biblioteca, desde una perspectiva de uso, ha cambiado poco. Por ejemplo...
> List("Paris", "London").map(_.length)
res0: List[Int] List(5, 6)
... funcionaría en cualquiera de las versiones. La biblioteca es eminentemente utilizable : de hecho, es fantástica. Sin embargo, aquellos que antes no estaban familiarizados con Scala y hurgando para familiarizarse con el idioma ahora tienen que entender las firmas de métodos como:
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That
Para una funcionalidad tan simple, esta es una firma desalentadora y una que me cuesta entender. No es que piense que Scala probablemente sea el próximo Java (o / C / C ++ / C #). No creo que sus creadores lo apunten a ese mercado, pero creo que es / era ciertamente factible que Scala se convirtiera el próximo Ruby o Python (es decir, para ganar una importante base de usuarios comerciales)
- ¿Esto va a disuadir a la gente de venir a Scala?
- ¿Esto le dará a Scala un mal nombre en el mundo comercial como un juego académico que solo los estudiantes de doctorado dedicados pueden entender? ¿Los CTO y los jefes de software se asustarán?
- ¿Fue la biblioteca rediseñada una idea sensata?
- Si está utilizando Scala comercialmente, ¿le preocupa esto? ¿Planea adoptar 2.8 inmediatamente o esperar a ver qué sucede?
Steve Yegge una vez atacó a Scala (erróneamente en mi opinión) por lo que vio como su sistema de tipos demasiado complicado. Me preocupa que alguien tenga un día de campo difundiendo FUD con esta API (de manera similar a cómo Josh Bloch asustó al JCP de agregar cierres a Java).
Nota : debo tener claro que, si bien creo que Joshua Bloch influyó en el rechazo de la propuesta de cierre de BGGA, no atribuyo esto a otra cosa que no sea su creencia sincera de que la propuesta representa un error.
A pesar de lo que mi esposa y mis compañeros de trabajo me dicen, no creo que sea un idiota: tengo un buen título en matemáticas de la Universidad de Oxford , y he estado programando comercialmente durante casi 12 años y en Scala durante aproximadamente un año (también comercialmente).
Tenga en cuenta que el título de tema inflamatorio es una cita hecha sobre el manifiesto de un partido político del Reino Unido a principios de la década de 1980 . Esta pregunta es subjetiva, pero es una pregunta genuina, la hice a la derecha y me gustaría tener algunas opiniones al respecto.
fuente
Respuestas:
Espero que no sea una "nota de suicidio", pero puedo ver su punto. Te encuentras con lo que es al mismo tiempo una fortaleza y un problema de Scala: su extensibilidad . Esto nos permite implementar la mayoría de las funciones principales en las bibliotecas. En algunos otros idiomas, las secuencias con algo como
map
ocollect
se construirían, y nadie tiene que ver todos los aros por los que tiene que pasar el compilador para que funcionen sin problemas. En Scala, todo está en una biblioteca y, por lo tanto, a la intemperie.De hecho, la funcionalidad de
map
que es compatible con su tipo complicado es bastante avanzada. Considera esto:¿Ves cómo siempre obtienes el mejor tipo posible? Si asigna
Int
s aInt
s, obtiene de nuevo aBitSet
, pero si asignaInt
s aString
s, obtiene un generalSet
. Tanto el tipo estático como la representación en tiempo de ejecución del resultado del mapa dependen del tipo de resultado de la función que se le pasa. Y esto funciona incluso si el conjunto está vacío, por lo que la función nunca se aplica. Hasta donde sé, no hay otro marco de colección con una funcionalidad equivalente. Sin embargo, desde la perspectiva del usuario, así es como se supone que funcionan las cosas .El problema que tenemos es que toda la tecnología inteligente que hace que esto suceda se filtra en las firmas tipo que se vuelven grandes y aterradoras. Pero tal vez un usuario no debería mostrar por defecto la firma de tipo completo de
map
? ¿Qué tal si ella alzó la vistamap
enBitSet
ella consiguió:Los documentos no estarían en ese caso, porque desde la perspectiva del usuario, de hecho, el mapa tiene el tipo
(Int => Int) => BitSet
. Peromap
también tiene un tipo más general que puede inspeccionarse haciendo clic en otro enlace.Todavía no hemos implementado funcionalidades como esta en nuestras herramientas. Pero creo que debemos hacer esto, para evitar asustar a la gente y dar más información útil. Con herramientas como esa, esperamos que los marcos y bibliotecas inteligentes no se conviertan en notas suicidas.
fuente
No tengo un doctorado, ni ningún otro tipo de título, ni en CS ni en matemáticas, ni en ningún otro campo. No tengo experiencia previa con Scala ni ningún otro lenguaje similar. No tengo experiencia incluso con sistemas de tipo remotamente comparables. De hecho, el único lenguaje que tengo más que un conocimiento superficial del cual incluso tiene un sistema de tipos es Pascal, no exactamente conocido por su sofisticado sistema de tipos. (A pesar de que hace tener tipos de rango, que yo sepa prácticamente ningún otro idioma tiene, pero eso no es realmente relevante aquí.) Los otros tres idiomas que conozco son básicas, Smalltalk y Ruby, ninguno de los cuales ni siquiera un sistema de tipos.
Y, sin embargo, no tengo ningún problema para comprender la firma de la
map
función que publicaste. Me parece más o menos la misma firma quemap
tiene en todos los demás idiomas que he visto. La diferencia es que esta versión es más genérica. Parece más una cosa C ++ STL que, por ejemplo, Haskell. En particular, se abstrae del tipo de colección concreta al solo requerir que el argumento seaIterableLike
, y también se abstrae del tipo de retorno concreto al solo requerir que exista una función de conversión implícita que pueda construir algo a partir de esa colección de valores de resultados. Sí, eso es bastante complejo, pero realmente es solo una expresión del paradigma general de la programación genérica: no asumas nada que realmente no tengas que hacer.En este caso, en
map
realidad no necesita que la colección sea una lista, que se ordene o que se pueda ordenar o algo así. Lo único quemap
le importa es que puede obtener acceso a todos los elementos de la colección, uno tras otro, pero sin ningún orden en particular. Y no necesita saber cuál es la colección resultante, solo necesita saber cómo construirla. Entonces, eso es lo que requiere su firma de tipo.Entonces, en lugar de
cuál es la firma de tipo tradicional
map
, se generaliza para no requerir una estructura de datos concretaList
sino más bienIterableLike
que luego se generaliza al requerir solo que exista una función que pueda convertir el resultado a cualquier estructura de datos que el usuario desee:
Admito que la sintaxis es un poco más complicada, pero la semántica es la misma. Básicamente, comienza desde
que es la firma tradicional para
map
. (Observe cómo, debido a la naturaleza orientada a objetos de Scala, el parámetro de la lista de entrada desaparece, porque ahora es el parámetro receptor implícito que tiene cada método en un sistema OO de despacho único). Luego se generalizó de un concretoList
a uno más generalIterableLike
Ahora, reemplaza la
IterableLike
colección de resultados con una función que produce , bueno, realmente casi cualquier cosa.Que realmente no creo es que difícil de entender. Realmente solo necesitas un par de herramientas intelectuales:
map
es. Si admitió solo la firma de tipo sin el nombre del método, lo admito, sería mucho más difícil averiguar qué está sucediendo. Pero como ya sabe lo quemap
se supone que debe hacer, y sabe cuál es su firma de tipo, puede escanear rápidamente la firma y enfocarse en las anomalías, como "¿por qué estomap
toma dos funciones como argumentos, no una?"Ninguno de estos tres debería causar dolor de cabeza a ningún programador profesional o incluso aficionado.
map
ha sido una función estándar en casi todos los idiomas diseñados en los últimos 50 años, el hecho de que diferentes idiomas tengan una sintaxis diferente debería ser obvio para cualquiera que haya diseñado un sitio web con HTML y CSS y no puede suscribirse a una programación remota lista de correo relacionada sin algunos fanáticos molestos de C ++ de la iglesia de St. Stepanov explicando las virtudes de la programación genérica.Sí, Scala es complejo. Sí, Scala tiene uno de los sistemas de tipos más sofisticados conocidos por el hombre, rivalizando e incluso superando lenguajes como Haskell, Miranda, Clean o Cyclone. Pero si la complejidad fuera un argumento contra el éxito de un lenguaje de programación, C ++ habría muerto hace mucho tiempo y todos estaríamos escribiendo Scheme. Hay muchas razones por las cuales Scala probablemente no tendrá éxito, pero el hecho de que los programadores no se molesten en encender sus cerebros antes de sentarse frente al teclado probablemente no sea el principal.
fuente
That
infiere y vincula al tipo,B
siendo una pregunta que viene a la mente. ¿De dónde vienen las implicidades de ser otro? Incluso sin estas observaciones detalladas, personalmente siento que esta es una firma compleja. ¡Pero evidentemente hay personas como tú que no están impresionadas por esto en absoluto!Lo mismo en C ++ :
fuente
func
debe ser un parámetro de plantilla, y debe usarresult_of
yis_callable
para obtener los otros tipos y restringir la sobrecarga adecuadamente :-)Bueno, puedo entender tu dolor, pero, francamente, las personas como tú y yo, o casi cualquier usuario habitual de Stack Overflow, no son la regla.
Lo que quiero decir con eso es que ... a la mayoría de los programadores no les importará ese tipo de firma, porque nunca los verán ! No leen la documentación.
Mientras vean algún ejemplo de cómo funciona el código, y el código no les falla en producir el resultado que esperan , nunca mirarán la documentación. Cuando eso falla, verán la documentación y esperarán ver ejemplos de uso en la parte superior.
Con estas cosas en mente, creo que:
Cualquiera (como en la mayoría de las personas) que alguna vez se encuentre con esa firma tipo se burlará de Scala sin fin si está predispuesto en su contra, y lo considerará un símbolo del poder de Scala si les gusta Scala.
Si la documentación no se mejora para proporcionar ejemplos de uso y explicar claramente para qué sirve un método y cómo usarlo, puede afectar un poco la adopción de Scala.
A la larga, no importará. Que Scala pueda hacer cosas así hará que las bibliotecas escritas para Scala sean mucho más potentes y seguras de usar. Estas bibliotecas y marcos atraerán a programadores atraídos por herramientas poderosas.
Los programadores a quienes les gusta la simplicidad y la franqueza continuarán usando PHP o lenguajes similares.
Por desgracia, los programadores de Java están muy interesados en las herramientas eléctricas, por lo que, al responder eso, acabo de revisar mis expectativas de la adopción de Scala. No tengo ninguna duda de que Scala se convertirá en un lenguaje convencional. No C-mainstream, sino quizás Perl-mainstream o PHP-mainstream.
Hablando de Java, ¿alguna vez reemplazaste el cargador de clases? ¿Alguna vez has visto lo que eso implica? Java puede dar miedo, si nos fijamos en los lugares que hacen los escritores de marcos. Es solo que la mayoría de la gente no lo hace. Lo mismo se aplica a Scala, en mi humilde opinión, pero los primeros usuarios tienden a mirar debajo de cada roca que encuentran, para ver si hay algo escondido allí.
fuente
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 pero cierto.Sí, pero también evitará que las personas se desanimen. He considerado que la falta de colecciones que usan tipos de tipo superior es una gran debilidad desde que Scala obtuvo soporte para tipos de tipo superior. Hace que los documentos de API sean más complicados, pero realmente hace que el uso sea más natural.
Algunos probablemente lo harán. No creo que Scala sea accesible para muchos desarrolladores "profesionales", en parte debido a la complejidad de Scala y en parte debido a la falta de voluntad de muchos desarrolladores para aprender. Los CTO que emplean a tales desarrolladores se asustarán con razón.
Absolutamente. Hace que las colecciones encajen mucho mejor con el resto del lenguaje y el sistema de tipos, incluso si todavía tiene algunos bordes ásperos.
No lo estoy usando comercialmente. Probablemente esperaré hasta al menos un par de revoluciones en la serie 2.8.x antes de intentar introducirla para que los errores puedan eliminarse. También esperaré para ver cuánto éxito tiene EPFL en mejorar sus procesos de desarrollo y lanzamiento. Lo que veo parece esperanzador, pero trabajo para una empresa conservadora.
Uno de los temas más generales de "¿Scala es demasiado complicado para los desarrolladores convencionales?" ...
La mayoría de los desarrolladores, convencionales o de otro tipo, mantienen o extienden los sistemas existentes. Esto significa que la mayoría de lo que usan está dictado por decisiones tomadas hace mucho tiempo. Todavía hay mucha gente escribiendo COBOL.
El desarrollador principal del mañana trabajará manteniendo y ampliando las aplicaciones que se están creando hoy. Muchas de estas aplicaciones no están siendo desarrolladas por los principales desarrolladores. Los desarrolladores principales del mañana utilizarán el lenguaje que utilizan los desarrolladores de nuevas aplicaciones más exitosos de la actualidad.
fuente
Una forma en que la comunidad de Scala puede ayudar a calmar el miedo de los programadores nuevos en Scala es centrarse en la práctica y enseñar con el ejemplo, muchos ejemplos que comienzan poco a poco y crecen gradualmente. Aquí hay algunos sitios que toman este enfoque:
Después de pasar un tiempo en estos sitios, uno se da cuenta rápidamente de que Scala y sus bibliotecas, aunque quizás sean difíciles de diseñar e implementar, no son tan difíciles de usar, especialmente en los casos comunes.
fuente
Tengo un título universitario de una universidad estadounidense barata de "mercado masivo", por lo que diría que me encuentro en el medio de la escala de inteligencia del usuario (o al menos educación) :) He estado incursionando en Scala durante solo unos meses. y he trabajado en dos o tres aplicaciones no triviales.
Especialmente ahora que IntelliJ ha lanzado su IDE fino con lo que IMHO es actualmente el mejor complemento de Scala, el desarrollo de Scala es relativamente sencillo:
Creo que puedo usar Scala como un "Java sin punto y coma", es decir, escribo un código similar al que haría en Java, y me beneficio un poco de la brevedad sintáctica como la obtenida por la inferencia de tipos. El manejo de excepciones, cuando lo hago, es más conveniente. La definición de clase es mucho menos detallada sin la placa captadora getter / setter.
De vez en cuando me las arreglo para escribir una sola línea para lograr el equivalente de varias líneas de Java. Cuando corresponda, las cadenas de métodos funcionales como mapear, plegar, recolectar, filtrar, etc. son divertidas de componer y elegantes de contemplar.
Solo en raras ocasiones me encuentro beneficiándome de las características más potentes de Scala: cierres y funciones parciales (o currificadas), coincidencia de patrones ... esa clase de cosas.
Como novato, sigo luchando con la sintaxis breve e idiomática. Las llamadas a métodos sin parámetros no necesitan paréntesis, excepto donde lo hacen; los casos en la declaración de coincidencia necesitan una flecha gruesa (
=>
), pero también hay lugares donde necesita una flecha delgada (->
). Muchos métodos tienen nombres cortos pero bastante crípticos como/:
o\:
: puedo hacer mis cosas si volteo suficientes páginas del manual, pero parte de mi código termina pareciéndose a Perl o ruido de línea. Irónicamente, falta una de las partes más populares de la taquigrafía sintáctica: sigo siendo mordido por el hecho de queInt
no define un++
método.Esta es solo mi opinión: siento que Scala tiene el poder de C ++ combinado con la complejidad y legibilidad de C ++. La complejidad sintáctica del lenguaje también hace que la documentación de la API sea difícil de leer.
Scala está muy bien pensado y es brillante en muchos aspectos. Sospecho que a muchos académicos les encantaría programar en él. Sin embargo, también está lleno de inteligencia y trucos, tiene una curva de aprendizaje mucho más alta que Java y es más difícil de leer. Si escaneo los foros y veo cuántos desarrolladores siguen luchando con los puntos más delicados de Java, no puedo concebir que Scala se convierta en un lenguaje convencional . Ninguna compañía podrá justificar el envío de sus desarrolladores a un curso de Scala de 3 semanas cuando antes solo necesitaban un curso de Java de 1 semana.
fuente
Creo que el principal problema con ese método es que
(implicit bf : CanBuildFrom[Repr, B, That])
no tiene ninguna explicación. Aunque sé qué argumentos implícitos hay, no hay nada que indique cómo esto afecta la llamada. Perseguir el scaladoc solo me deja más confundido (pocas de las clases relacionadas conCanBuildFrom
incluso tienen documentación).Creo que un simple "no debe ser un objeto implícito en posibilidades de
bf
que proporciona un constructor de objetos de tipoB
en el tipo de retornoThat
" ayudarían un poco, pero es una especie de concepto embriagadora cuando todo lo que realmente quiere hacer es el mapaA
que está aB
's. De hecho, no estoy seguro de que sea correcto, porque no sé quéRepr
significa el tipo y la documentación paraTraversable
ciertamente no da ninguna pista.Entonces, me quedan dos opciones, ninguna de las cuales es agradable:
Entiendo que Scala esencialmente está exponiendo las agallas de cómo funcionan estas cosas y que, en última instancia, esto es una forma de hacer lo que oxbow_lakes está describiendo. Pero es una distracción en la firma.
fuente
Repr
es la representación transitable, es decir.List
oSet
oMap
. Creo que, como marco, si va a comenzar a buscar firmas de métodos (en lugar de usar los métodos copiando ejemplos), primero debe comprender el diseño general. En mi humilde opinión, el Scaladoc debería estar lleno de ejemplos de usoRepr
significaba? Esperaría una explicación en el scaladoc, pero realmente no era obvio para mí. Creo que este es un patrón común en el scaladoc (miraActor.react
yActor.receive
, me han dicho, y he visto, que hacen cosas totalmente diferentes, pero su scaladoc es idéntico).Soy un principiante de Scala y, sinceramente, no veo ningún problema con ese tipo de firma. El parámetro es la función para mapear y el parámetro implícito el constructor para devolver la colección correcta. Claro y legible.
Todo el asunto es bastante elegante, en realidad. Los parámetros de tipo de generador permiten al compilador elegir el tipo de retorno correcto, mientras que el mecanismo de parámetro implícito oculta este parámetro adicional al usuario de la clase. Intenté esto:
Eso es polimorfismo bien hecho.
Ahora, concedido, no es un paradigma convencional y asustará a muchos. Pero, también atraerá a muchos que valoran su expresividad y elegancia.
fuente
Lamentablemente, la firma para el mapa que proporcionó es incorrecta y, de hecho, hay críticas legítimas.
La primera crítica es que al subvertir la firma del mapa, tenemos algo más general. Es un error común creer que esto es una virtud por defecto. No lo es La función de mapa está muy bien definida como un functor covariante Fx -> (x -> y) -> Fy con adherencia a las dos leyes de composición e identidad. Cualquier otra cosa atribuida al "mapa" es una parodia.
La firma dada es otra cosa, pero no es un mapa. Lo que sospecho que está tratando de ser es una versión especializada y ligeramente alterada de la firma "transversal" del documento, La esencia del patrón iterador. Aquí está su firma:
Lo convertiré a Scala:
Por supuesto que falla, ¡no es lo suficientemente general! Además, es ligeramente diferente (tenga en cuenta que puede obtener el mapa al recorrer el functor de Identidad). Sin embargo, sospecho que si los escritores de la biblioteca fueran más conscientes de las generalizaciones de la biblioteca que están bien documentadas (la Programación Aplicativa con Efectos precede a lo mencionado anteriormente), entonces no veríamos este error.
Segundo, la función de mapa es un caso especial en Scala debido a su uso en comprensiones for. Desafortunadamente, esto significa que un diseñador de biblioteca mejor equipado no puede ignorar este error sin sacrificar también el azúcar sintáctico de las comprensiones. En otras palabras, si los diseñadores de la biblioteca Scala tuvieran que destruir un método, entonces esto se ignora fácilmente, ¡pero no haga un mapa!
Espero que alguien hable al respecto, porque tal como es, será más difícil solucionar los errores que Scala insiste en cometer, aparentemente por razones a las que tengo fuertes objeciones. Es decir, la solución a "las objeciones irresponsables del programador promedio (es decir, ¡demasiado difícil!") No es "apaciguarlos para que sea más fácil para ellos", sino proporcionar sugerencias y asistencia para convertirse en mejores programadores. Los objetivos de Scala y yo están en disputa sobre este tema, pero volviendo a su punto.
Probablemente estaba haciendo su punto, prediciendo respuestas específicas del "programador promedio". Es decir, las personas que reclamarán "¡pero es demasiado complicado!" o algo por el estilo. Estos son los Yegges o Blochs a los que te refieres. Mi respuesta a estas personas del movimiento anti-intelectualismo / pragmatismo es bastante dura y ya estoy anticipando un aluvión de respuestas, por lo que lo omitiré.
Realmente espero que las bibliotecas de Scala mejoren, o al menos, los errores se puedan guardar de forma segura en un rincón. Java es un lenguaje en el que "tratar de hacer algo útil" es tan increíblemente costoso que a menudo no vale la pena porque la gran cantidad de errores simplemente no se pueden evitar. Le suplico a Scala que no siga el mismo camino.
fuente
Estoy totalmente de acuerdo con la pregunta y la respuesta de Martin :). Incluso en Java, leer javadoc con genéricos es mucho más difícil de lo debido debido al ruido adicional. Esto se agrava en Scala, donde los parámetros implícitos se usan como en el código de ejemplo de las preguntas (mientras que los implícitos hacen cosas muy útiles para la transformación de la colección).
No creo que sea un problema con el lenguaje per se, creo que es más un problema de herramientas. Y aunque estoy de acuerdo con lo que dice Jörg W Mittag, creo que mirar scaladoc (o la documentación de un tipo en su IDE): debería requerir la menor potencia cerebral posible para entender qué es un método, qué se necesita y qué se devuelve. No debería ser necesario hackear un poco de álgebra en un poco de papel para obtenerlo :)
Por supuesto, los IDE necesitan una buena manera de mostrar todos los métodos para cualquier variable / expresión / tipo (que, como en el ejemplo de Martin, puede tener todos los genéricos en línea, por lo que es agradable y fácil de asimilar). También me gusta la idea de Martin de ocultar las implicidades por defecto.
Para tomar el ejemplo en scaladoc ...
Al mirar esto en scaladoc, me gustaría que el bloque genérico [B, That] se oculte de forma predeterminada, así como el parámetro implícito (tal vez se muestre si se pasa un pequeño icono con el mouse), ya que es algo adicional para grok leerlo que generalmente no es tan relevante. por ejemplo, imagina si esto pareciera ...
agradable y claro y obvio lo que hace. Quizás se pregunte qué es 'Eso', si pasa el mouse o hace clic en él, podría expandir el texto [B, That] resaltando el 'Eso' por ejemplo.
Tal vez podría usarse un pequeño ícono para la declaración [] y el bloque (implícito ...) para que quede claro que hay pequeños fragmentos de la declaración colapsados. Es difícil usar un token, pero usaré un. por ahora...
Entonces, por defecto, el 'ruido' del sistema de tipos está oculto del 80% principal de lo que la gente necesita mirar: el nombre del método, sus tipos de parámetros y su tipo de retorno de una manera simple, concisa y agradable, con pequeños enlaces expandibles al detalle si realmente te importa tanto.
La mayoría de las personas están leyendo scaladoc para averiguar qué métodos pueden invocar en un tipo y qué parámetros pueden pasar. Estamos sobrecargando a los usuarios con demasiados detalles sobre cómo en mi humilde opinión.
Aquí hay otro ejemplo ...
Ahora, si ocultamos la declaración de genéricos, es más fácil de leer
Entonces, si la gente se detiene, digamos, A1, podríamos mostrar que la declaración de A1 es A1 <: A. Los tipos covariantes y contravariantes en genéricos también agregan mucho ruido, lo que se puede representar de una manera mucho más fácil de entender para los usuarios, creo.
fuente
No sé cómo decírtelo, pero tengo un doctorado de Cambridge y estoy usando 2.8 muy bien.
Más en serio, apenas pasé tiempo con 2.7 (no interactuará con una biblioteca Java que estoy usando) y comencé a usar Scala hace poco más de un mes. Tengo algo de experiencia con Haskell (no mucho), pero ignoré las cosas que te preocupan y busqué métodos que coincidieran con mi experiencia con Java (que uso para vivir).
Entonces: soy un "nuevo usuario" y no me desanimé; el hecho de que funcione como Java me dio suficiente confianza para ignorar los bits que no entendí.
(Sin embargo, la razón por la que estaba mirando a Scala era en parte para ver si debía presionarlo en el trabajo, y no lo voy a hacer todavía. Hacer que la documentación sea menos intimidante ciertamente ayudaría, pero lo que me sorprendió es cuánto es todavía cambiando y desarrollándose (para ser justos, lo que más me sorprendió fue lo increíble que es, pero los cambios llegaron en un segundo lugar). Así que supongo que lo que estoy diciendo es que prefiero los recursos limitados para ponerlo en práctica. un estado final: no creo que esperaran ser tan populares tan pronto).
fuente
No conozco a Scala en absoluto, sin embargo, hace unas semanas no pude leer Clojure. Ahora puedo leer la mayor parte, pero no puedo escribir nada más allá de los ejemplos más simplistas . Sospecho que Scala no es diferente. Necesitas un buen libro o curso dependiendo de cómo aprendas. Solo leyendo la declaración del mapa anterior, tal vez tengo 1/3 de ella.
Creo que los problemas más grandes no son la sintaxis de estos lenguajes, sino adoptar e internalizar los paradigmas que los hacen utilizables en el código de producción cotidiano. Para mí, Java no fue un gran salto de C ++, que no fue un gran salto de C, que no fue un salto de Pascal, ni Basic, etc. ... Pero codificar en un lenguaje funcional como Clojure es un gran salto (para yo de cualquier forma). Supongo que en Scala puedes codificar en estilo Java o estilo Scala. Pero en Clojure crearás un gran desastre tratando de mantener tus hábitos imperativos de Java.
fuente
Scala tiene muchas características locas (particularmente en lo que respecta a parámetros implícitos) que se ven muy complicadas y académicas, pero están diseñadas para facilitar el uso. Los más útiles obtienen azúcar sintáctica (como lo
[A <% B]
que significa que un objeto de tipo A tiene una conversión implícita en un objeto de tipo B) y una explicación bien documentada de lo que hacen. Pero la mayoría de las veces, como cliente de estas bibliotecas, puede ignorar los parámetros implícitos y confiar en que hagan lo correcto.fuente
No creo que sea el factor principal que afectará la popularidad de Scala, porque Scala tiene mucho poder y su sintaxis no es tan extraña para un programador Java / C ++ / PHP como Haskell, OCaml, SML, Lisps, etc.
Pero sí creo que la popularidad de Scala se estabilizará en menos de lo que está Java hoy, porque también creo que el próximo lenguaje principal debe simplificarse mucho, y la única forma en que veo para llegar allí es pura inmutabilidad, es decir, declarativa como HTML, pero Turing completo . Sin embargo, soy parcial porque estoy desarrollando un lenguaje así, pero solo lo hice después de descartar durante un estudio de varios meses que Scala no podía ser suficiente para lo que necesitaba.
No creo que la reputación de Scala se vea afectada por el complejo Haskell. Pero creo que algunos pospondrán su aprendizaje, porque para la mayoría de los programadores, todavía no veo un caso de uso que los obligue a usar Scala, y postergarán el aprendizaje al respecto. Quizás el lado del servidor altamente escalable es el caso de uso más convincente.
Y, para el mercado convencional, el primer aprendizaje de Scala no es un "soplo de aire fresco", en el que se escriben programas de inmediato, como el primer uso de HTML o Python. Scala tiende a crecer en ti, después de que uno aprende todos los detalles que uno tropieza desde el principio. Sin embargo, tal vez si hubiera leído Programación en Scala desde el principio, mi experiencia y opinión sobre la curva de aprendizaje habría sido diferente.
Seguro.
Estoy usando Scala como la plataforma inicial de mi nuevo idioma. Probablemente no estaría construyendo código en la biblioteca de colección de Scala si estuviera usando Scala comercialmente de lo contrario. Crearía mi propia biblioteca basada en la teoría de categorías, ya que una vez que busqué, encontré las firmas de tipo de Scalaz aún más detalladas y difíciles de manejar que la biblioteca de colección de Scala. Parte de ese problema quizás sea la forma en que Scala implementa las clases de tipos, y esa es una razón menor por la que estoy creando mi propio lenguaje.
Decidí escribir esta respuesta, porque quería obligarme a investigar y comparar el diseño de la clase de colección de Scala con el que estoy haciendo para mi idioma. También podría compartir mi proceso de pensamiento.
El uso de las colecciones 2.8 Scala de una abstracción de constructor es un principio de diseño de sonido. Quiero explorar dos compensaciones de diseño a continuación.
CÓDIGO SOLO PARA ESCRIBIR: Después de escribir esta sección, leí el comentario de Carl Smotricz que está de acuerdo con lo que espero sea la compensación. Los comentarios de James Strachan y davetron5000 coinciden en que el significado de Eso (ni siquiera es Eso [B]) y el mecanismo de lo implícito no es fácil de entender intuitivamente. Vea mi uso de monoid en el número 2 a continuación, que creo que es mucho más explícito. El comentario de Derek Mahar es sobre escribir Scala, pero ¿qué pasa con la lectura de Scala de otros que no está "en los casos comunes"?
Una crítica que he leído sobre Scala es que es más fácil escribirlo que leer el código que otros han escrito. Y creo que esto es cierto ocasionalmente por varias razones (por ejemplo, muchas formas de escribir una función, cierres automáticos, Unidad para DSL, etc.), pero no estoy seguro si este es un factor importante. Aquí el uso de parámetros de funciones implícitas tiene más y menos. En el lado positivo, reduce la verbosidad y automatiza la selección del objeto generador. En Odersky's ejemplola conversión de un BitSet, es decir, Set [Int], a un Set [String] es implícita. Es posible que el lector desconocido del código no sepa fácilmente cuál es el tipo de colección, a menos que pueda razonar bien sobre todos los posibles candidatos constructores implícitos invisibles que podrían existir en el alcance del paquete actual. Por supuesto, el programador experimentado y el escritor del código sabrán que BitSet está limitado a Int, por lo tanto, un mapa de String debe convertirse a un tipo de colección diferente. ¿Pero qué tipo de colección? No se especifica explícitamente.
DISEÑO DE COLECCIÓN AD-HOC: Después de escribir esta sección, leí el comentario de Tony Morris y me di cuenta de que estoy haciendo casi lo mismo. Quizás mi exposición más detallada hará que el punto sea más claro.
En "Fighting Bit Rot with Type" Odersky & Moors, se presentan dos casos de uso. Son la restricción de BitSet a elementos Int, y Map para emparejar elementos de tupla, y se proporcionan como la razón por la cual la función general de mapeo de elementos, A => B, debe ser capaz de construir tipos de colección de destino alternativos. Sin embargo, afaik esto es defectuoso desde una perspectiva de teoría de categoría. Para ser coherente en la teoría de categorías y evitar así los casos de esquina, estos tipos de colección son functores, en los que cada morfismo, A => B, debe mapearse entre objetos en la misma categoría de functor, Lista [A] => Lista [B], BitSet [A] => BitSet [B]. Por ejemplo, una Opción es un functor que se puede ver como una colección de conjuntos de un Some (objeto) y el None. No existe un mapa general de Option's None, o List's Nil, a otros functors que no '
Hay una elección de diseño de compensación hecha aquí. En el diseño de la biblioteca de colecciones de mi nuevo idioma, elegí hacer de todo un functor, lo que significa que si implemento un BitSet, debe admitir todos los tipos de elementos, mediante el uso de una representación interna de campo no bit cuando se presenta un parámetro de tipo entero, y esa funcionalidad ya está en el conjunto que hereda de Scala. Y Map en mi diseño necesita mapear solo sus valores, y puede proporcionar un método no functor separado para mapear sus tuplas de pares (clave, valor). Una ventaja es que cada functor suele ser también un aplicativo y quizás también una mónada. Por lo tanto, todas las funciones entre los tipos de elementos, por ejemplo, A => B => C => D => ..., se levantan automáticamente a las funciones entre los tipos aplicativos levantados, por ejemplo, Lista [A] => Lista [B] => Lista [ C] => Lista [D] => .... Para el mapeo de un functor a otra clase de colección, ofrezco una sobrecarga de mapeo que toma un monoide, por ejemplo, Nil, None, 0, "", Array (), etc. Por lo tanto, la función de abstracción del generador es el método append de un monoide y se suministra explícitamente como un parámetro de entrada necesario, por lo tanto, sin conversiones implícitas invisibles. (Tangente: este parámetro de entrada también permite agregar monoides no vacíos, lo que el diseño del mapa de Scala no puede hacer). Tales conversiones son un mapa y un pliegue en el mismo paso de iteración. También proporciono un McBride & Patterson, "en sentido de categoría," Programable aplicativo con efectos ", que también permite mapa + pliegue en un solo paso de iteración de cualquier objeto transitable a cualquier aplicativo, donde la mayoría de las clases de colección son ambas.
Entonces, las colecciones de Scala son "ad-hoc" en el sentido de que no se basan en la teoría de categorías, y la teoría de categorías es el sentido de la semántica denotacional de nivel superior. Aunque los constructores implícitos de Scala son a primera vista "más generalizados" que un modelo de functor + constructor de monoides + transitables -> aplicativos, no se ha demostrado que sean consistentes con ninguna categoría, por lo que no sabemos qué reglas siguen en el sentido más general y cuáles serán los casos de esquina, es posible que no obedezcan ningún modelo de categoría. Simplemente no es cierto que agregar más variables hace que algo sea más general, y este fue uno de los enormes beneficios de la teoría de categorías, ya que proporciona reglas para mantener la generalidad mientras se eleva a la semántica de nivel superior. Una colección es una categoría.
Leí en alguna parte, creo que fue Odersky, como otra justificación para el diseño de la biblioteca, es que la programación en un estilo funcional puro tiene el costo de una recursión y velocidad limitadas donde no se usa la recursión de cola. No me ha resultado difícil emplear la recursividad de la cola en todos los casos que he encontrado hasta ahora.
Además, tengo en mente una idea incompleta de que algunas de las compensaciones de Scala se deben a que intentan ser un lenguaje mutable e inmutable, a diferencia, por ejemplo, de Haskell o del lenguaje que estoy desarrollando. Esto coincide con el comentario de Tony Morris sobre las comprensiones. En mi lenguaje, no hay bucles ni construcciones mutables. Mi lenguaje se ubicará en la parte superior de Scala (por ahora) y le debe mucho, y esto no sería posible si Scala no tuviera el sistema de tipo general y la mutabilidad. Sin embargo, eso podría no ser cierto, porque creo que Odersky & Moors ("Fighting Bit Rot with Type") son incorrectos al afirmar que Scala es el único lenguaje OOP con tipos superiores, porque verifiqué (yo mismo y a través de Bob Harper) que Standard ML los tiene. También parece que el sistema de tipos de SML puede ser igualmente flexible (desde 1980), lo cual puede no apreciarse fácilmente porque la sintaxis no es muy similar a Java (y C ++ / PHP) como Scala. En cualquier caso, esto no es una crítica de Scala, sino más bien un intento de presentar un análisis incompleto de las compensaciones, que espero sea pertinente para la pregunta. Scala y SML no sufren la incapacidad de Haskell para hacerherencia múltiple de diamantes , lo cual es crítico y entiendo por qué tantas funciones en el Preludio de Haskell se repiten para diferentes tipos.
fuente
Parece necesario indicar los títulos aquí: BA en Ciencias Políticas y B.ed en Ciencias de la Computación.
Al punto:
Scala es difícil, porque su paradigma de programación subyacente es difícil. La programación funcional asusta a mucha gente. Es posible construir cierres en PHP, pero la gente rara vez lo hace. Entonces no, no esta firma, pero todo lo demás desanimará a las personas, si no tienen la educación específica para que valoren el poder del paradigma subyacente.
Si esta educación está disponible, todos pueden hacerlo. ¡El año pasado construí una computadora de ajedrez con un grupo de niños de escuela en SCALA! Tuvieron sus problemas pero al final lo hicieron bien.
No estaría preocupado
fuente
¡También tengo un título en matemáticas de Oxford! Me llevó un tiempo 'obtener' las nuevas colecciones. Pero me gusta mucho ahora que lo hago. De hecho, escribir 'mapa' fue una de las primeras cosas importantes que me molestó en 2.7 (quizás porque lo primero que hice fue la subclase una de las clases de colección).
Leer el documento de Martin sobre las nuevas colecciones 2.8 realmente ayudó a explicar el uso de implicidades, pero sí, la documentación en sí misma definitivamente necesita hacer un mejor trabajo al explicar el papel de los diferentes tipos de implicidades dentro de las firmas de métodos de las API principales.
Mi principal preocupación es más esto: ¿cuándo se lanzará 2.8? ¿Cuándo dejarán de aparecer los informes de errores? ¿El equipo Scala ha mordido más de lo que puede masticar con 2.8 / ha tratado de cambiar demasiado a la vez?
Realmente me gustaría ver 2.8 estabilizado para el lanzamiento como una prioridad antes de agregar algo nuevo en absoluto, y me pregunto (mientras observa desde la barrera) si se podrían hacer algunas mejoras en la forma en que se gestiona la hoja de ruta de desarrollo para el compilador de scala.
fuente
¿Qué pasa con los mensajes de error en el sitio de uso?
Y qué pasa con el caso de uso que uno necesita para integrar los tipos existentes con uno personalizado que se ajuste a un DSL. Uno tiene que estar bien educado en asuntos de asociación, precedencia, conversiones implícitas, parámetros implícitos, clases superiores y quizás tipos existenciales.
Es muy bueno saber que, en su mayoría, es simple, pero no necesariamente es suficiente. Al menos debe haber un tipo que sepa esto si se va a diseñar una biblioteca generalizada.
fuente