¿Es la biblioteca de colecciones Scala 2.8 un caso de "la nota de suicidio más larga de la historia"? [cerrado]


873

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.


10
fud solo representa miedo, incertidumbre y duda: creo que eso expresa con bastante claridad el tono de la charla de Josh Bloch, que también estoy de acuerdo, está bien argumentado y razonado, etc. Si ves las ediciones, originalmente no puse fud porque no quería dar a entender connotaciones -ve
oxbow_lakes

32
Esta pregunta fue mencionada en la charla de apertura de Martin Odersky en Scala Days 2010 days2010.scala-lang.org/node/136
Binil Thomas el

77
Lo que me encanta de Scala es que no tienes que entender que es un sistema de tipo complejo para hacer cosas simples y elegantes. su sintaxis puede ser desalentadora, pero te asegura una cosa, no hay "magia", por ejemplo, la magia es parte del lenguaje, es un enfoque muy valiente e inteligente, creo que tienes un lenguaje que puede crear nuevas DSL y nuevas mini idiomas dentro de sí mismo, sí, con las manos equivocadas Scala puede ser una excelente adición a su cena italiana, pero una vez que se acostumbra, es un idioma increíble
Eran Medan

87
¿Cómo puede esta pregunta ser "no constructiva" cuando llevó a @MartinOdersky a reevaluar la usabilidad de Scala y hacer que su sistema de documentación oculte detalles del sistema de tipos, sin mencionar una discusión esclarecedora?
Jerry101 01 de

14
De hecho, SO es solo para tecnicismos con el formato correcto. Si tiene algo delicado, intrigante y de gran alcance, busque en otro lado. Larga vida a la mentalidad burocrática.
qed

Respuestas:


892

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 mapo collectse 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 mapque es compatible con su tipo complicado es bastante avanzada. Considera esto:

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

¿Ves cómo siempre obtienes el mejor tipo posible? Si asigna Ints a Ints, obtiene de nuevo a BitSet, pero si asigna Ints a Strings, obtiene un general Set. 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 vista mapen BitSetella consiguió:

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

Los documentos no estarían en ese caso, porque desde la perspectiva del usuario, de hecho, el mapa tiene el tipo (Int => Int) => BitSet. Pero maptambié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.


107
¡Me siento como un niño travieso! Muchas gracias por tomarse el tiempo de responder aquí. Creo que el balance de respuestas me ha demostrado que no necesito preocuparme; habrá suficientes personas que no se sientan intimidadas en absoluto.
oxbow_lakes

164
No, creo que tenías toda la razón al acertar en ese punto. Y otras personas tendrán miedo a menos que hagamos algo al respecto.
Martin Odersky el

33
Martin, me gusta tu sugerencia para mostrar un método simplificado de firmas y ocultar los detalles generales detrás de un enlace.
Derek Mahar el

18
Creo que una solución que funcionaría al menos también es más explicaciones en los documentos. No encontraría las firmas tan intimidantes, si no fuera por el hecho de que la mayoría de los métodos (e incluso la mayoría de las clases) no tienen más que una sola oración que describa su propósito y operación.
Nick Johnson

98
Actualización: La versión final de Scala 2.8 tiene un mecanismo como el que describí. Si busca BitSet en los scaladocs, encontrará: def map [B] (f: (Int) ⇒ B): BitSet [B] [use case] Crea una nueva colección aplicando una función a todos los elementos de este conjunto de bits.
Martin Odersky

226

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 mapfunción que publicaste. Me parece más o menos la misma firma que maptiene 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 sea IterableLike, 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 maprealidad no necesita que la colección sea una lista, que se ordene o que se pueda ordenar o algo así. Lo único que maple 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

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

cuál es la firma de tipo tradicional map, se generaliza para no requerir una estructura de datos concreta Listsino más bienIterableLike

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

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:

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

Admito que la sintaxis es un poco más complicada, pero la semántica es la misma. Básicamente, comienza desde

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

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 concreto Lista uno más generalIterableLike

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

Ahora, reemplaza la IterableLikecolección de resultados con una función que produce , bueno, realmente casi cualquier cosa.

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

Que realmente no creo es que difícil de entender. Realmente solo necesitas un par de herramientas intelectuales:

  1. Necesita saber (aproximadamente) qué mapes. 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 que mapse 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é esto maptoma dos funciones como argumentos, no una?"
  2. Debe poder leer realmente la firma de tipo. Pero incluso si nunca antes ha visto Scala, esto debería ser bastante fácil, ya que en realidad es solo una mezcla de sintaxis de tipos que ya conoce de otros idiomas: VB.NET usa corchetes para el polimorfismo paramétrico, y usa una flecha para denotar el tipo de retorno y dos puntos para separar el nombre y el tipo, es en realidad la norma.
  3. Necesita saber aproximadamente de qué se trata la programación genérica. (Que no es que difícil de entender, ya que es básicamente todo lo explicado en el nombre: está literalmente a la programación de un modo genérico).

Ninguno de estos tres debería causar dolor de cabeza a ningún programador profesional o incluso aficionado. mapha 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.


36
@Jorg: esa es una respuesta increíble; gracias. Ya sea que tengas un título o no, eres un hombre más brillante que yo. La única objeción que tengo es que entiendo el panorama general de lo que está sucediendo en la firma del método. Sin embargo, los detalles siguen siendo confusos: cómo se Thatinfiere y vincula al tipo, Bsiendo 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!
oxbow_lakes

50
Buena explicación, pero me ha convencido aún más de que la firma del método de "mapa" Scala 2.8 es muy complicada.
Derek Mahar el

11
Un lenguaje que se parece a esto: def map [B] (f: (A) ⇒ B): IterableLike [B] es mucho más atractivo que uno que se ve así: def map [B, That] (f: A ⇒ B ) (implícito bf: CanBuildFrom [Repr, B, That]): Eso
Mark Essel

215
Me parece bastante interesante que comience afirmando que solo conoce conocimientos básicos, rubí y smalltalk, y continúe diciendo que no tiene antecedentes académicos en el tema. ... y luego reclamando conocimiento sobre la complejidad de los sistemas de tipos en lenguajes como Miranda y Clean; lenguajes conocidos principalmente entre lenguajes de programación serios geeks y académicos.
Sami

14
Tiene un punto válido de que la comparación con Haskell es incorrecta en que "map :: (a -> b) -> [a] -> [b]" es específico de las Listas. Sin embargo, la versión generalizada, la de la clase Functor, sigue siendo mucho más simple que la versión Scala: class Functor f donde fmap :: (a -> b) -> fa -> fb
Orclev

175

Lo mismo en 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
... y dicen que Scala es oscura. Duh!
missingfaktor

24
Imagínense cómo habría sido si se hubieran utilizado identificadores autodescriptivos adecuados en lugar de letras mayúsculas arbitrarias. :-)
Ti Strga

14
Es útil ver esta comparación, pero sería más justo si se omitiera la implementación.
Aaron Novstrup

2
No soy un gran admirador del puntero de función obligatorio. Claramente, el tipo de funcdebe ser un parámetro de plantilla, y debe usar result_ofy is_callablepara obtener los otros tipos y restringir la sobrecarga adecuadamente :-)
Kerrek SB

1
me duelen los ojos !!!
Ashkan Kh. Nazary

71

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:

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

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

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

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


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 pero cierto.
gamliela

99
@gamliela, no creo que estemos tristes por esto. El conocimiento siempre tiene más de un nivel para aplicar, y el trabajo y la confianza de otros (revisados ​​por pares) en cualquier sistema siempre se pueden aprovechar, al igual que usamos la aritmética diariamente e ignoramos totalmente las álgebras de miedo que funcionan detrás de él.
lcn

55

¿Esto va a disuadir a la gente de venir a Scala?

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.

¿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?

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.

¿Fue la biblioteca rediseñada una idea sensata?

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.

Si usa Scala comercialmente, ¿le preocupa esto? ¿Planea adoptar 2.8 inmediatamente o esperar a ver qué sucede?

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.


31
"También evitará que las personas se desanimen". esta. absolutamente. Scala es el primer lenguaje que hace que la ingeniería con algo comparable a Haskell (en el poder de su sistema de tipos) sea una posibilidad para muchos de nosotros. no hay manera de que pueda convencer al trabajo de que use haskell, pero scala realmente tiene una oportunidad y por eso me encanta y (cuando creo que tiene sentido) intentaré que sea adoptado, o al menos aceptado, en el trabajo.
Andrew Cooke

+1 de mi parte también. Dada la premisa de que Scala pone más énfasis en la profundidad y el rigor lingüístico que en la accesibilidad masiva, estas respuestas se ajustan perfectamente.
Carl Smotricz

16
"Los desarrolladores principales del mañana utilizarán el lenguaje que utilizan los desarrolladores de nuevas aplicaciones más exitosos de la actualidad". +1. Dijo brillantemente.
Vasil Remeniuk

46

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.


43

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.


99
Perdón por todos los comentarios. 1 semana es una broma para prácticamente cualquier idioma, pero eso no impide que los gerentes pongan en práctica esa broma. Una vez me dieron 3 días para "entrenar en choque" a un grupo de desarrolladores de C ++ en Java. Pedí 5 días pero me quedé corto por razones de presupuesto.
Carl Smotricz

22
Para mi primer trabajo, me dieron un libro de C ++ al final de la entrevista para aprender antes de comenzar a trabajar el lunes. Todos ustedes son cobardes.
Tom Hawtin - tackline

12
@Tom @Erik Ustedes muchachos lo tienen fácil. Me dieron los diagramas de circuito a la computadora (sin CPU en ese entonces), y me dijeron que tenía dos horas para arreglar un error en la entrevista.
Daniel C. Sobral

33
@Daniel @Tom @Erik Una vez me dieron un 0 y un 1 y me pidieron que los usara para resolver el problema de la mochila en tiempo lineal durante la entrevista. Le di una oportunidad, pero desafortunadamente solo tuve tiempo para crear Eclipse (que sospecho que es reducible a mochila). #tall_tale
Alex Miller

10
@Alex Eso muestra falta de imaginación. Coloque un cero grande a la izquierda y otros dos ceros más pequeños a la derecha: uno encima del otro, el superior ligeramente a la izquierda. Coloque el uno entre estos dos ceros más pequeños, yendo desde la parte inferior izquierda hasta la parte superior derecha. Digamos que es la oportunidad de resolver la mochila en tiempo lineal. Ya terminaste. :-) +1 para equiparar Eclipse y Mochila, sin embargo. :-)
Daniel C. Sobral

33

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 bfque proporciona un constructor de objetos de tipo Ben el tipo de retorno That" ayudarían un poco, pero es una especie de concepto embriagadora cuando todo lo que realmente quiere hacer es el mapa Aque está a B's. De hecho, no estoy seguro de que sea correcto, porque no sé qué Reprsignifica el tipo y la documentación paraTraversable ciertamente no da ninguna pista.

Entonces, me quedan dos opciones, ninguna de las cuales es agradable:

  • Suponga que solo funcionará cómo funciona el mapa antiguo y cómo funciona el mapa en la mayoría de los otros idiomas
  • Cavar en el código fuente un poco más

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.


2
Repres la representación transitable, es decir. Listo Seto Map. 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 uso
oxbow_lakes

10
Entonces, ¿cómo habría determinado qué Reprsignificaba? 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 (mira Actor.reacty Actor.receive, me han dicho, y he visto, que hacen cosas totalmente diferentes, pero su scaladoc es idéntico).
davetron5000

77
Estoy de acuerdo con davetron5000. Estoy bastante familiarizado con Scala, pero las definiciones implícitas todavía me duelen la cabeza. Y la razón no está implícita per se sino cómo se usan. Definitivamente debería haber una mejor documentación y soporte de herramientas para comprender los tipos de Scala. Dicho esto, creo que el sistema de tipos realmente tiene algo importante que ofrecer. Pero todavía estamos en el comienzo del camino de la programación sensata.
egaga

22

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:

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

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.


20

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:

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

Lo convertiré a Scala:

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

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.


3
Hola Tony, gracias por tu aportación reflexiva aquí. Haría 2 respuestas a eso. La primera es que no mencioné el "programador promedio" y no creo que Scala esté necesariamente dirigido a uno. Ya sea que esté presumido de mí o de otra manera, creo que estoy por encima del promedio; Sin embargo, ¡todavía siento que la firma tipográfica es desalentadora! Todavía me preocupa, en otras palabras, que los programadores superiores al promedio, el mercado objetivo de Scala, puedan ser expulsados.
oxbow_lakes

66
El segundo punto es que estoy básicamente en desacuerdo contigo sobre qué es Scala: Scala es un lenguaje pragmático, no teóricamente puro. ¿Por qué si no habría sido diseñado encima de la JVM? Esta es una decisión puramente pragmática: está dirigida a los desarrolladores "en el mundo real", ¡una elección que puede haber requerido compromisos! También tenga en cuenta que Bloch y Yegge están lejos de ser programadores promedio, pero ese es mi punto. Incluso las personas muy respetadas e inteligentes pueden tener opiniones sobre la complejidad y la pureza que difieren de las suyas. Desafortunadamente para ti, también son muy influyentes.
oxbow_lakes

3
Hola oxbow_lakes, Scala tiene el objetivo declarado de apaciguar a los programadores típicos, incluso a expensas de la precisión y la practicidad. Los programadores superiores a la media se alejan (tengo varias anécdotas), pero no porque las firmas de tipo sean abrumadoras, sino por la naturaleza de algunos de los errores. No dije que Scala sea o no sea pragmático o teórico. Además, ni siquiera me suscribo a la idea (¿común?) De que tal dicotomía existe. Las bibliotecas de Scala han atornillado la firma del mapa. Llevo años trabajando en los errores de Scala; particularmente las bibliotecas. Es hora de hacerlo de nuevo.
Tony Morris el

55
No considero que Bloch o Yegge sean muy respetados o inteligentes, pero son bastante influyentes. Sí, esto es lamentable.
Tony Morris el

99
¿Por qué te relacionas con la firma extendida de Scala? El mapa de Scala, para monofunctores, es el fmap estándar. Pero ni BitSet ni Map [A, B] son ​​monofunctores, sin embargo, map tiene en ellos una definición significativa. Esa es la motivación de la firma de Scala, y el recorrido no resuelve este problema. ¿Por qué la generalidad es algo malo? Los functores aplicados rastrean los efectos, ¿cuál es su punto en Scala? Finalmente, creo que el mapa genérico de Scala se puede implementar en términos de un recorrido generalizado, aceptando un CanBuildFrom y devolviendo un Traversable potencialmente diferente: ¡no hay necesidad de sacrificarse por las comprensiones!
Blaisorblade

15

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

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

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

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

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

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

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

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

Ahora, si ocultamos la declaración de genéricos, es más fácil de leer

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

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.


55
Pero, ¿qué significa "Eso" como un tipo de resultado?
Blaisorblade

11

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


22
Creo que quiere saber si las personas sin doctorado de Cambridge pueden manejar Scala 2.8.
Ken Bloom

2
Jaja: touche! Bueno, dije que scala 2.8 es fácil de usar: mi pregunta era más sobre cómo sería para alguien que navega por la API para ver si les gusta, suponiendo que no tenían experiencia previa en Scala.
oxbow_lakes

1
@andrew: desde el aspecto de su sitio web ( acooke.org ), no se siente incómodo con los conceptos visualmente intimidantes
oxbow_lakes

Cualquiera que esté ocupado con la programación de Malbolge, incluso si es "solo" Hello World, es poco probable que se sienta intimidado por algo.
Carl Smotricz

10

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.


55
Nunca se trata de notación (o nunca más que, digamos, 10-15% sobre notación), siempre se trata de conceptos. Y si eres razonablemente inteligente y no estás empantanado en décadas de conocimiento de modelos diferentes y posiblemente contradictorios (como probablemente lo soy), entonces generalmente no es demasiado difícil comprender estas cosas. Pero si está inmerso en una forma de pensar y hacer cosas, entonces es al menos un esfuerzo adaptarse y muchos reaccionan contra tales cambios. Es solo psicología humana / naturaleza. (Me pregunto cómo se mantendrá la Psicología de la Programación de Computadoras de Weinberg después de casi 40 años.)
Randall Schulz

1
@Randall Schultz y Jeff G: la sintaxis / notación es razonablemente fácil para una persona inteligente. Diferentes nombres para los mismos conceptos, básicamente. Ponerse al día en un nuevo idioma es solo una cuestión de práctica. SIN EMBARGO, el paso de la programación procesal a la funcional es ... terriblemente amplio. Es realmente una forma diferente de pensar. He estado jugando con Clojure durante algunos meses y me parece un lenguaje FP relativamente "fácil" y agradable. Pero todavía necesito una cantidad excesiva de tiempo para resolver cosas que serían sencillas en la programación de procedimientos.
Carl Smotricz

7

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.


Sí, ver la sintaxis hace que las cosas sean más rápidas de entender.
egaga

6

¿Esto va a disuadir a la gente de venir a Scala?

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.

¿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?

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.

¿Fue la biblioteca rediseñada una idea sensata?

Seguro.

Si está utilizando Scala comercialmente, ¿le preocupa esto? ¿Planea adoptar 2.8 inmediatamente o esperar a ver qué sucede?

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.

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

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


Entonces, ¿tu lenguaje estará orientado a objetos?
missingfaktor

Sí, hereda el sistema de tipos de Scala. Una distinción clave es que el rasgo se divide en interfaz y mixin, donde la interfaz contiene solo firmas de métodos y ninguna implementación. Y solo se puede hacer referencia a una interfaz como tipo. Las implicidades se eliminan y las clases de tipo se manejan de forma SPOT en la interfaz. Aquí hay un borrador de detalles. Los colaboradores son bienvenidos. Algún código para la biblioteca está aquí . Este es un trabajo en progreso, disculpas por mencionar vaporware. Solo compartiendo pensamientos.
Shelby Moore III el

5

Parece necesario indicar los títulos aquí: BA en Ciencias Políticas y B.ed en Ciencias de la Computación.

Al punto:

¿Esto va a disuadir a la gente de venir a Scala?

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.

Si está utilizando Scala comercialmente, ¿le preocupa esto? ¿Planea adoptar 2.8 inmediatamente o esperar a ver qué sucede?

No estaría preocupado


4

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


-1

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


Pero uno de los puntos principales es la diferencia entre la biblioteca desde la perspectiva de un usuario y los creadores. Obviamente, los creadores necesitan una comprensión impresionante de las características del lenguaje requeridas (por ejemplo, tipos de clase superior, precedencia implícita). La pregunta es: "¿los usuarios?"
oxbow_lakes
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.