studio reales proyectos programacion libro introducción incluye herramientas fundamentos fuente español código con avanzado aplicaciones c++ scala operator-overloading

reales - ¿Qué hace que el operador de Scala sobrecargue "bien", pero C++ es "malo"?



libro de android studio en español pdf (14)

La sobrecarga del operador en C ++ es considerada por muchos como A Bad Thing (tm), y un error que no debe repetirse en los idiomas más nuevos. Ciertamente, fue una característica específicamente eliminada al diseñar Java.

Ahora que comencé a leer en Scala, me parece que tiene algo que se parece mucho a la sobrecarga del operador (aunque técnicamente no tiene sobrecarga del operador porque no tiene operadores, solo funciones). Sin embargo, no parece ser cualitativamente diferente a la sobrecarga del operador en C ++, donde, como recuerdo, los operadores se definen como funciones especiales.

Entonces mi pregunta es ¿qué hace que la idea de definir "+" en Scala sea una mejor idea que en C ++?


La sobrecarga del operador en C ++ es considerada por muchos como A Bad Thing (tm)

Solo por el ignorante Es absolutamente necesario en un lenguaje como C ++, y es notable que otros lenguajes que comenzaron teniendo una visión "purista", lo han agregado una vez que sus diseñadores descubrieron lo necesario que es.


Sin embargo, no parece ser cualitativamente diferente a la sobrecarga del operador en C ++, donde, como recuerdo, los operadores se definen como funciones especiales.

AFAIK, No hay nada especial en las funciones del operador en comparación con las funciones de miembros "normales". Por supuesto, solo tienes un cierto conjunto de operadores que puedes sobrecargar, pero eso no los hace muy especiales.


C ++ hereda los verdaderos operadores azules de C. Con esto quiero decir que el "+" en 6 + 4 es muy especial. No puede, por ejemplo, obtener un puntero a esa función +.

Scala, por otro lado, no tiene operadores de esa manera. Simplemente tiene una gran flexibilidad para definir nombres de métodos más un poco de precedencia incorporada para símbolos que no son palabras. Entonces, técnicamente, Scala no tiene sobrecarga del operador.

Como sea que quieras llamarlo, la sobrecarga del operador no es inherentemente mala, incluso en C ++. El problema es cuando los programadores malos lo abusan. Pero, francamente, soy de la opinión de que quitarle a los programadores la capacidad de abusar de la sobrecarga de los operadores no supone una gota en la trampa de arreglar todas las cosas que los programadores pueden abusar. La verdadera respuesta es la tutoría. http://james-iry.blogspot.com/2009/03/operator-overloading-ad-absurdum.html

Sin embargo, existen diferencias entre la sobrecarga del operador de C ++ y el método flexible de Scala que, en mi humilde opinión, hace que Scala sea menos abusable y más abusable.

En C ++, la única forma de obtener notación in-fix es usar operadores. De lo contrario, debe usar object.message (argument) o pointer-> messsage (argument) o function (argument1, argument2). Entonces, si desea un cierto estilo DSLish para su código, entonces existe la presión de usar operadores.

En Scala puedes obtener notación infija con cualquier mensaje enviado. "argumento de mensaje de objeto" está perfectamente bien, lo que significa que no necesita usar símbolos que no sean palabras solo para obtener una notación infija.

La sobrecarga del operador C ++ se limita esencialmente a los operadores C. Combinado con la limitación de que solo los operadores pueden usar infix que ejerce presión sobre las personas para tratar de asignar una amplia gama de conceptos no relacionados a un número relativamente pequeño de símbolos como "+" y ">>"

Scala permite una gran variedad de símbolos válidos que no son palabras como nombres de métodos. Por ejemplo, tengo un DSL Prolog-ish integrado donde puedes escribir

female(''jane)! // jane is female parent(''jane,''john)! // jane is john''s parent parent(''jane, ''wendy)! // jane is wendy''s parent mother(''Mother, ''Child) :- parent(''Mother, ''Child) & female(''Mother) //''// a mother of a child is the child''s parent and is female mother(''X, ''john)? // find john''s mother mother(''jane, ''X)? // find''s all of jane''s children

Los símbolos: -,!,? Y & se definen como métodos ordinarios. Solo en C ++ sería válido, por lo que un intento de asignar esta DSL a C ++ requeriría algunos símbolos que ya evocan conceptos muy diferentes.

Por supuesto, esto también abre Scala a otro tipo de abuso. En Scala puedes nombrar un método $! & ^% Si lo deseas.

Para otros lenguajes que, como Scala, son flexibles en el uso de funciones y nombres de métodos no ver palabras, vea Smalltalk donde, como Scala, cada "operador" es solo otro método y Haskell que permite al programador definir precedencia y fijeza de nombre flexible funciones.


Como las otras respuestas han señalado; la sobrecarga del operador en sí no es necesariamente mala. Lo que es malo cuando se usa de formas que hacen que el código resultante no sea obvio. En general, al usarlos, es necesario que hagan lo menos sorprendente (tener la división operator + do causaría problemas para el uso de una clase racional) o, como dice Scott Meyers:

Los clientes ya saben cómo se comportan los tipos como int, por lo que debes esforzarte para que tus tipos se comporten de la misma manera siempre que sea razonable ... En caso de duda, haz lo que hacen los ints . (Del artículo 18 de Effective C ++ 3rd Edition)

Ahora, algunas personas han llevado la sobrecarga del operador al extremo con cosas como boost::spirit . En este nivel, no tienes idea de cómo se implementa, pero crea una sintaxis interesante para obtener lo que quieres que se haga. No estoy seguro de si esto es bueno o malo. Parece agradable, pero no lo he usado.


Creo que CADA respuesta se perdió esto. En C ++ puede sobrecargar a los operadores todo lo que quiera, pero no puede afectar la precedencia con la que se evalúan. Scala no tiene este problema, IIRC.

En cuanto a que es una mala idea, además de los problemas de precedencia, las personas tienen un significado realmente tonto para los operadores, y raramente ayuda a la lectura. Las bibliotecas de Scala son especialmente malas para esto, símbolos tontos que debes memorizar cada vez, con los mantenedores de la biblioteca pegando sus cabezas en la arena diciendo, ''solo necesitas aprenderlo una vez''. Genial, ahora necesito aprender la sintaxis críptica de un autor "inteligente" * la cantidad de bibliotecas que me interesa usar. No sería tan malo si existiera una convención de SIEMPRE suministrar una versión alfabetizada de los operadores.


En general, no es algo malo.
Los nuevos lenguajes como C # también tienen sobrecarga del operador.

Es el abuso de la sobrecarga del operador lo que es malo.

Pero también hay problemas con la sobrecarga del operador como se define en C ++. Debido a que los operadores sobrecargados son solo azúcar sintáctico para las llamadas a métodos, se comportan como el método. Por otro lado, los operadores incorporados normales no se comportan como métodos. Estas inconsistencias pueden causar problemas.

Fuera de la cabeza de los operadores || y && .
Las versiones integradas de estos son operadores de acceso directo. Esto no es cierto para las versiones sobrecargadas y ha causado algunos problemas.

El hecho de que + - * / todos devuelva el mismo tipo en que operan (después de la promoción del operador)
Las versiones sobrecargadas pueden devolver cualquier cosa (aquí es donde se establece el abuso, si sus operadores comienzan a devolver algún tipo de árbitro, el usuario no esperaba que las cosas cayeran).


Este artículo - " The Positive Legacy of C ++ and Java " - responde su pregunta directamente.

"C ++ tiene asignación de pila y asignación de montón y debe sobrecargar a sus operadores para manejar todas las situaciones y no causar pérdidas de memoria. De hecho, es difícil. Java tiene un único mecanismo de asignación de almacenamiento y un recolector de basura, lo que hace que la sobrecarga del operador sea trivial". ..

Java por error (según el autor) omitió la sobrecarga del operador porque era complicado en C ++, pero olvidó por qué (o no se dio cuenta de que no se aplicaba a Java).

Afortunadamente, los lenguajes de nivel superior como Scala brindan opciones a los desarrolladores, mientras se ejecutan en la misma JVM.


Guy Steele argumentó que la sobrecarga de operadores también debería estar en Java, en su discurso de apertura "Growing a language" (Creciendo un idioma), hay un video y una transcripción de él, y es realmente un discurso increíble. Te preguntarás de qué está hablando durante las primeras páginas, pero si sigues leyendo, verás el punto y lograrás la iluminación. Y el solo hecho de que él pudiera hacer tal discurso en absoluto también es sorprendente.

Al mismo tiempo, esta charla inspiró una gran cantidad de investigaciones fundamentales, probablemente incluyendo Scala, es uno de esos documentos que todos deberían leer para trabajar en el campo.

Volviendo al punto, sus ejemplos son principalmente sobre clases numéricas (como BigInteger y algunas cosas más extrañas), pero eso no es esencial.

Es cierto, sin embargo, que el mal uso de la sobrecarga del operador puede llevar a resultados terribles, y que incluso los usos adecuados pueden complicar las cosas, si intenta leer el código sin estudiar un poco las bibliotecas que utiliza. ¿Pero es una buena idea? OTOH, ¿no deberían esas bibliotecas intentar incluir una hoja de trucos para sus operadores?


La sobrecarga del operador no era una invención de C ++: provenía de Algol IIRC e incluso Gosling no afirma que sea una mala idea en general.


La sobrecarga del operador no es algo que realmente "necesites" muy a menudo, pero cuando usas Java, si llegas al punto donde realmente lo necesitas, te dará ganas de arrancarte las uñas para tener una excusa para dejar de escribir. .

¿Ese código que acabas de encontrar desborda mucho? Sí, vas a tener que volver a escribir todo para que funcione con BigInteger. No hay nada más frustrante que tener que reinventar la rueda solo para cambiar el tipo de una variable.


La sobrecarga del operador nunca se pensó universalmente como una mala idea en C ++: solo se pensaba que el abuso de la sobrecarga del operador era una mala idea. En realidad, no es necesario sobrecargar al operador en un idioma, ya que se pueden simular con más llamadas de funciones detalladas de todos modos. Evitar la sobrecarga del operador en Java hizo que la implementación y la especificación de Java fueran un poco más simples y obligó a los programadores a no abusar de los operadores. Ha habido cierto debate en la comunidad Java sobre la introducción de la sobrecarga del operador.

Las ventajas y desventajas de la sobrecarga del operador en Scala son las mismas que en C ++: puede escribir un código más natural si usa la sobrecarga del operador de forma apropiada y, si no lo hace, un código oculto y oculto.

FYI: Los operadores no están definidos como funciones especiales en C ++, se comportan como cualquier otra función, aunque existen algunas diferencias en la búsqueda de nombres, ya sea que necesiten ser funciones miembro, y el hecho de que se pueden llamar de dos maneras: 1 ) sintaxis del operador, y 2) sintaxis del operador-función-id.


Lo único conocido erróneo en C ++ es la falta de la capacidad de sobrecargar [] = como un operador separado. Esto podría ser difícil de implementar en un compilador de C ++ por lo que probablemente no sea una razón obvia, pero vale la pena.


No hay nada de malo con la sobrecarga del operador. De hecho, hay algo mal en no tener sobrecarga del operador para los tipos numéricos. (Eche un vistazo a algunos códigos Java que usan BigInteger y BigDecimal).

Sin embargo, C ++ tiene una tradición de abusar de la característica. Un ejemplo frecuentemente citado es que los operadores de desplazamiento de bits están sobrecargados para hacer E / S.


Nunca he visto un artículo que afirme que la sobrecarga del operador de C ++ es mala.

Los operadores definibles por el usuario permiten un mayor nivel de expresividad y facilidad de uso para los usuarios del idioma.