¿Cómo diseñarías un lenguaje de programación? [cerrado]

41

Si diseñaras un lenguaje de programación, ¿cómo lo harías? ¿Qué características pondrías? ¿Qué dejarías fuera? ¿Mecanografiado estática o dinámicamente? ¿Fuerte o débilmente tipeado? Compilado o interpretado? Justifica tus respuestas.

Chinmay Kanchi
fuente
12
Esta pregunta es muy vaga. Las características del lenguaje no pueden discutirse realmente hasta que se determine el propósito del idioma.
blucz
1
Si puede votar y cree que esta es una pregunta útil o tiene respuestas útiles a continuación, vote por favor. Los sitios de StackExchange necesitan votos para construir una buena comunidad. Puedes dar 30 votos por día, no los desperdicies. Especialmente los usuarios con alta reputación y votos contados bajos, lean esto: meta.programmers.stackexchange.com/questions/393/…
Maniero
3
Crearía un lenguaje de muy alto nivel con un método: public void DoWhatIMeant ();
Dave
66
¿El lenguaje de programación ideal? ... Obtendría que el compilador lea mi mente y genere un programa exactamente como lo quiero ... :) podría tomar un tiempo pero valdría la pena.
WalterJ89
2
La compilación y la interpretación son rasgos de ... bueno, el compilador o intérprete (duh), no el lenguaje. Todos los idiomas pueden ser implementados por un compilador o un intérprete. Y de hecho, casi todos lo son. Hay compiladores para Ruby, Python, ECMAScript, PHP, hay intérpretes para C, C ++, Java, Haskell, ...
Jörg W Mittag

Respuestas:

55
  • Definitivamente creo que los lenguajes de programación funcionales se pondrán al día, por lo que mi lenguaje será funcional. Ver Efectos de domesticación con programación funcional

  • Creo que las CPU pronto tendrán cientos de núcleos, y los hilos serán un infierno para administrar. Entonces, el modelo de actor es imprescindible en lugar de hilos. Ver Erlang - software para un mundo concurrente

  • También creo que OOP ha fallado, se suponía que la comunicación entre objetos era asíncrona . Así que creo que necesitamos pasar mensajes , con mensajes inmutables. Enviar y olvidar. Como en el modelo de actor. Consulte Programación orientada a objetos: ¿el camino equivocado?

  • Creo que sería bueno tener una escritura estática , por lo que los errores se detectan antes en el ciclo de desarrollo. Pero usaría la inferencia de tipos como en Haskell, para que el desarrollador no necesite escribir el tipo en todas partes del código como en C, C # y Java. Vea Aprenda usted un Haskell para un gran bien

  • También diseñaría una gran biblioteca de interfaz de usuario , con diseño declarativo , como en WPF y Android. Pero me gustaría tenerlo como en la programación funcional reactiva .

Entonces, mi lenguaje sería como la concurrencia en Erlang pero con la escritura como en Haskell y un marco GUI como en WPF.NET.

Jonas
fuente
44
suena como Scala, en realidad, excepto por la gran biblioteca de UI.
Ape-inago
Pensé que Scala tenía mensajes y actores. Supongo que no sé cómo se relaciona eso con OOP.
Ape-inago
@Jonas: se ve genial :) No sé mucho sobre el modelo de actor, ¿es similar a lo que hizo Go con las gorutinas?
Matthieu M.
1
De lo único que soy escéptico es de la escritura estática. Definitivamente preferiría la escritura fuerte en lugar de la débil, pero a veces la escritura estática es demasiado restrictiva. Pero no estoy familiarizado con Haskell, y solo he oído cosas buenas sobre su sistema de escritura :)
sakisk
1
La falla de OOP, francamente, es que casi ningún lenguaje "orientado a objetos" realmente lo implementa . La mayoría simplemente calza un modelo de objeto en un lenguaje de procedimiento y lo llama un día. Desearía que Smalltalk se hubiera percatado más de sí mismo, en lugar de incitar a todos los weenie de lenguaje de procedimiento a decir "Eh, podemos hacer algo más o menos así" y lograr perder el punto de OOP por completo.
cHao
22

Nota: He usado la sintaxis tipo C para describir las características en esta publicación, pero no soy exigente con la sintaxis en sí, siempre y cuando no sea algo ridículo como todas las palabras clave como MAYÚSCULAS.

1. sistema de mecanografía

La característica número uno que quisiera en un idioma es la escritura estática con la escritura dinámica opcional . La razón es que la escritura estática le permite a) detectar errores temprano en lugar de tarde yb) la mayoría del código está tipado estáticamente de forma implícita, independientemente de si el idioma hace o no la distinción. Sin embargo, hay varios casos de uso donde la tipificación dinámica es extremadamente útil. Por ejemplo, cuando lee datos de un archivo, a menudo tiene campos de diferentes tipos, y la escritura dinámica facilita los contenedores heterogéneos. Entonces, mi lenguaje ideal tendría algo como esto:

//variable declarations
int anInt = 42 //anInt is now irrevocably an integer and assigning another type to it is an error
vartype aVariable = 42 //aVariable is currently an integer, but any type can be assigned to it in the future

//function definitions
int countElements(Collection c)
{
  return c.count();
} 

//c HAS to be a collection, since countElements doesn't make sense otherwise

void addToCollection(Collection& c, vartype v) 
{
  c.append(v)
}

//c is passed by reference here

2. Compilado vs. Interpretado

Me gustaría que el lenguaje se compile con anticipación o que se compile JIT, pero no se interprete puramente, siendo la razón la velocidad. Esto se relaciona con el punto 1 , ya que un compilador / jitter optimizador tendrá mucho más tiempo optimizando el código tipado estáticamente, y el código tipado dinámicamente simplemente podría dejarse como está.

3. Cierres

El lenguaje debe admitir construcciones de programación funcional, y las funciones deben ser objetos de primera clase.

4. Orientado a objetos

El lenguaje debería permitirle escribir código orientado a objetos, pero también debería permitirse un código imperativo simple. es decir, debería ser posible escribir un programa hello world así:

int main(string<> args=null)
{
  printf("hello, world"); 
  return 0;
}

// this code also demonstrates two other features,
// default arguments for functions (not explained further)
// and immutable lists like string<> (see 6. Built-in datatypes)

5. Espacios de nombres

Los espacios de nombres son algo bueno. Muy pocas cosas deberían ir al espacio de nombres global. Pero si debe poner cosas en el espacio de nombres global, puede (ala C ++).

6. Tipos de datos incorporados

El lenguaje debe tener, como tipos de datos integrados, las siguientes construcciones:

  • Un inttipo de datos o tipos. Si solo hay un inttipo, debe tener un rango ilimitado. Si hay más, debería haber una conversión implícita en el tipo más pequeño capaz de contener el resultado de un cálculo, siendo el tipo de rango ilimitado el más grande.
  • Un único floattipo binario incorporado , que es equivalente a un IEEE 754double
  • Un listtipo mutable que se implementa como una lista doblemente vinculada o como un bloque de memoria contigua que contiene punteros a cada elemento
  • Un listtipo inmutable que actúa como una matriz pero cuyo tamaño no se puede cambiar después de la creación.
  • stringTipos mutables e inmutables , siendo el valor predeterminado inmutable.
  • Una mapo dicttipo que es mutable, y tiene teclas inmutables y valores mutables y / o inmutables.
  • Los tipos de colección incorporados deben ser de tipo homogéneo por defecto, pero se pueden vartyped si es necesario
  • Un booleantipo
  • A nullo nonetipo que se puede asignar a una variable de cualquier tipo.
  • setTipos mutables e inmutables
  • Un decimaltipo que implementa variables de coma flotante decimal
  • Un fixedtipo, que implementa un número de punto fijo

Los tipos decimal, floaty fixeddeben compartir exactamente la misma interfaz pública (ya sea a través de la herencia o la escritura de pato), lo que les permite pasar de forma transparente y regresar de las funciones. Se podría llamar al tipo principal real.

7. Llamada por valor y por referencia

Debería poder llamar a las funciones tanto por valor como por referencia, siendo el valor predeterminado (es decir, se realiza una copia del argumento y se opera en la función).

8. Punteros

El lenguaje debe tener punteros y permitir aritmética de punteros. Los punteros solo se pueden escribir estáticamente (para evitar la pesadilla que es a void*). vartypelos punteros están explícitamente prohibidos Tener punteros y aritmética de punteros permite que el lenguaje se use seriamente como lenguaje de programación de sistemas.

9. montaje en línea

En relación con 8. , El idioma debe permitir el código de lenguaje ensamblador en línea para aquellas situaciones donde sea necesario.

10. seguridad

El lenguaje debe ser seguro de usar, admitir el manejo de excepciones, etc. La aritmética del puntero y el ensamblaje en línea pueden relegarse a partes del código marcadas explícitamente como inseguras. Se permite código inseguro, pero se desaconseja encarecidamente.

11. Comportamiento indefinido

El estándar del lenguaje debe especificar cómo se comportará el programa en todas las circunstancias, excepto en el código marcado explícitamente como inseguro, es decir, no debe haber un comportamiento indefinido fuera de los bloques inseguros. Esto permite que el lenguaje se use como un lenguaje de desarrollo de aplicaciones viable, al tiempo que le permite decir, escribir un sistema operativo en él.

Eso es todo lo que puedo pensar en este momento, pero editaré / actualizaré la publicación a medida que piense en más cosas.

Chinmay Kanchi
fuente
55
Eche un vistazo al "Lenguaje de programación D": digitalmars.com/d
Wizard79
Hasta donde puedo recordar, D no tiene una tipificación dinámica opcional o un tipo entero de rango ilimitado incorporado. El tipo entero no es un gran problema, pero la falta de tipeo dinámico opcional lo hace poco atractivo.
Chinmay Kanchi
1
Realmente agregaría un decimaltipo aquí.
configurador
3
"Un tipo nulo o ninguno que se puede asignar a una variable de cualquier tipo". - ¿Incluye booleano? :-p
Timwi
1
No veo "flexible" en la publicación original. Inline Assembler no aparecería en mi mente como requisito principal para un lenguaje de programación. Tal vez eso es lo que dice Felix von Leitner hoy en día, escribir Assembler en su mayoría le da resultados lentos e incorrectos.
LennyProgrammers
7

Así es como se vería el lenguaje de programación de mis sueños:

  • Un poderoso sistema de tipo estático con algún soporte para tipeo dependiente.
  • Escritura dinámica opcional.
  • Torre numérica a la Lisp pero estáticamente escrita.
  • Macros a la Lisp.
  • Principalmente un lenguaje de programación funcional con soporte básico para la programación imperativa (como la familia ML).
  • Recolección de basura.
  • Tipo de inferencia.
  • Continuaciones
  • Semántica perezosa opcional.
  • Todas las construcciones de control se proporcionarían en forma de funciones de biblioteca. (Esto puede hacerse posible utilizando las dos últimas funciones).
  • Sintaxis mínima (no tan pequeña como Lisps, pero algo así como Ioke / Seph.)
missingfaktor
fuente
Suena bien. Sin embargo, realmente no he visto una buena manera de hacer macros estáticamente seguras.
Jörg W Mittag
@ Jörg: ¿Nemerle?
missingfaktor
En Smalltalk, todas las estructuras de control son en realidad métodos, y no utiliza continuaciones en su implementación. Uno no es necesario para el otro.
Roble
@Oak, ¿puedes implementar Python yielden Smalltalk? Debe ser tan limpio de usar.
missingfaktor
Un mecanismo similar al rendimiento ya está implementado en smalltalk como método de biblioteca, sin continuaciones.
Roble
6

Lo hubiera diseñado más o menos como C #, pero Microsoft me ganó. :)

(Excepto, por supuesto, que el mío hubiera sido menos pensado y más aficionado).

No me importa mucho si está compilado o interpretado, así que no necesito justificar ese bit.

En cuanto a la tipificación estática fuerte, me resulta difícil apreciar por qué esto incluso requiere justificación. La escritura estática es una característica que detecta errores durante el tiempo de compilación. La escritura dinámica es la falta de esa característica y difiere los errores hasta el tiempo de ejecución. En mi experiencia personal, tuve pocos casos de uso donde el despacho dinámico tenía sentido y era útil, por lo que las convoluciones que tuve que atravesar en C # antes de 4.0 para obtenerlo se justificaron fácilmente en ese momento. Con C # 4.0 ya ni siquiera necesito justificar eso porque ahora tenemos un despacho dinámico.

Sin embargo, probablemente habría creado una nueva sintaxis en lugar de apegarme tan religiosamente a la vieja sintaxis de C como lo hizo C #. La declaración de cambio es particularmente horrible, y tampoco me gusta la sintaxis de transmisión (es al revés). Sin embargo, no hago un gran alboroto sobre los detalles de la sintaxis, por lo que no necesito justificarlo en detalle, excepto que no quisiera que sea tan detallado como Visual Basic.

¿Qué más quieres que justifique?

Timwi
fuente
+1 Buena respuesta! Publicaré uno de los míos más tarde también.
Chinmay Kanchi
44
C # es un lenguaje poderoso, pero la sintaxis a menudo es desordenada. Creo que esto se debe a que muchas de estas características no estaban en el diseño original.
Casebash
De ahí "4.0", supongo.
Mark C
5

Bueno, aquí hay una lista de características que pondría:


Lisp como sintaxis

Estilo Lisp

Pros :

  • Sintaxis fácilmente extensible. ¿Alguna vez trató de implementar un bucle foreach en C? No es exactamente fácil. (Eso sí, lo he hecho ).
  • Homoiconicidad Puedes simplemente(eval "your data files")

Contras :

  • La notación polaca anidada es a menudo difícil de leer.

Programacion Funcional

Estilo Haskell

Pros :

  • Simultáneamente, todo el código es seguro para subprocesos.

Contras :

  • Es difícil implementar efectos secundarios en código funcional puro, aunque las mónadas parecen hacer un buen trabajo.

Fuerte tipificación dinámica

Estilo Python

Pros :

  • La escritura dinámica hace que el código sea legible, la escritura fuerte puede eliminar errores de escritura

implementación :

Permitir la sobrecarga de funciones en función de los tipos, similares a los CL defgeneric:

(define (+ (a <int>) (b <int>))
  (ints-add a b))

(define (+ (a <string>) (b <string>))
  (string-concat a b))

(define (+ a b)
  (add-generic a b))

Compilable e Interpretable

Pros :

  • Aumento del rendimiento si se compila (generalmente cierto, no siempre)

Contras :

  • Puede limitar las características en el lenguaje, aunque llvm sería un buen respaldo.

Programación de sistemas

Estilo C

Pros :

  • Apela a una gama de usuarios, muy ligeramente, más amplia.
  • Es más fácil para las aplicaciones, el kernel y los controladores de dispositivo interactuar si todos están escritos en el mismo idioma

Contras :

  • Limita las abstracciones en el lenguaje, la escritura dinámica a menudo no es adecuada.

Macros higiénicas (estilo CL y estilo Scheme)

Pros :

  • Fácil de extender el lenguaje, especialmente con la sintaxis Lispy ™
  • He dicho esto antes, ¿no?

Contras :

  • No muchos si se hace con la sintaxis Lispy ™

Ahora que lo pienso, este esquema más o menos define, a excepción del bit de compilación y programación de sistemas. Eso se puede solucionar usando libguile y escribiendo esos bits en C.

Joe D
fuente
1
Echa un vistazo a Ioke y Seph. Es sorprendente la facilidad de lectura de un lenguaje al agregar una cantidad de sintaxis muy pequeña en comparación con las S-Expressions y aún tener las capacidades macro completas. (Básicamente, en lugar de "cada llamada a una función es una lista y las listas son de primera clase" es "todo es un envío de mensajes y las cadenas de mensajes son de primera clase". En lugar de una lista cuya cares la función y cdrlos argumentos, tiene un objeto cuyo nameámbito es el método y cuyo argumentscampo es el argumento y en lugar de anidación, que tiene. prevy nextpuntero campos).
Jörg W Mittag
Sonidos casi exactamente como Clojure (suponiendo que el uso de Mjolnir generaltion código nativo en LLVM para los sistemas de programación de piezas - github.com/halgari/mjolnir )
mikera
3

Hay varios idiomas que considero bastante buenos (C # es mi favorito actual). Como este es mi lenguaje de fantasía, esto es lo que realmente quiero que tenga:

  • Documentación oficial de la API de kick-ass. La API de Java es buena así, y C # /. NET es bastante buena. Ruby / Rails es bastante terrible aquí.
  • Documentación general oficial de kick-ass (procedimientos, usos comunes, muchos códigos de ejemplo). C # /. Net es bueno para esto.
  • Una gran comunidad de documentadores basados ​​en blogs y solucionadores de problemas de StackOverflow para ayudarme a salir de situaciones difíciles
  • Una amplia gama de complementos / bibliotecas / extensiones bien respaldadas, bien documentadas y potentes (Ruby / Rails tiene 'poderoso' pero ninguno de los otros dos).
  • Es razonablemente estable: no cambia todo para romper la mayoría del código existente anualmente (mirándolo, Ruby / Rails).
  • No es demasiado estable, es capaz de adaptarse a los avances en el diseño del lenguaje (mirándote, c ++)
Fishtoaster
fuente
2
Los puntos de "documentación rápida" deben incluir PHP: D
Corey
3

Sugerencias del compilador

Estoy hablando de mí porque no sé mucho sobre el diseño del lenguaje, pero creo que la característica de la que estoy hablando se llama pistas en otros idiomas. Consejos del compilador , tal vez?

No sé si leí esto en un borrador de Perl6 o solo estaba alto en ese momento, pero me imagino un lenguaje en el que todo, por defecto, es flojo, pegajoso y automático. Pero si realmente desea aumentar el rendimiento y decir, oye, este valor siempre es un número entero o nunca es nulo, o puede ser paralelo, o no tiene estado, cosas así ... Que el compilador podría ir automáticamente a la ciudad en estas áreas marcadas específicamente.

E: Agradecería comentarios que aclaren lo que estoy pidiendo o que citen ejemplos donde esto ya existe.

Mark Canlas
fuente
1
Puede hacer algo de esto en Common Lisp. Por ejemplo, puede decirle al compilador que i es un número entero de tamaño razonable. Una cosa útil es que, al variar los valores safetyy speed, a menudo puede hacer que el compilador verifique y aplique (para encontrar problemas) o suponga que lo que dice es verdadero (y compila código más rápido).
David Thornley
2

Para probar nuevas ideas:

Haría un lenguaje de programación funcional de tipo dinámico, que le permite hacer todos los trucos de expresión de enunciados y la sintaxis lambda más simple con coincidencia de patrones. Regla fuera de juego habilitada.

// a view pattern (or Active Pattern in F#)
default = \def val: !!val.Type val def

// usage of the pattern
greet = \name<(default "world") `and` hasType Str>:
  p "Hello, \{name}!"

(p "Enter your name", .input).greet // (, ) is a sequence expression, returning the last value

Aquí hay una explicación:

default =establece el almacenamiento, \def valse inicia una función de curry con dos argumentos, val.Typees el mismo que Type[val], !!convertidos a Boolean, y boolean se puede aplicar, por lo que valydef are after it.

f x= f[x]= x.f .f=f[]

y en greet, se utiliza name<(default "world")y hasType Str>, significa que el patrón default "world"será utilizada y obligado a name. El patrón predeterminado especifica un valor predeterminado. andes otro patrón que encadena dos patrones juntos. el defaultpatrón no puede fallar mientras que hasTypepuede fallar. En ese caso, arroja una excepción.

Las variables son en realidad almacenamientos, que pueden pasarse funcionalmente, y las tablas de almacenamiento pueden ser referencias, creadas y destruidas a medida que cambian los ámbitos.

Los hashes y demás serán como en Lua y JavaScript.

Si voy a hacer un lenguaje compilado, voy a hacer un F # para Java, con características similares a las de Haskell. Es un lenguaje funcional puro, excepto que hay una característica que combina las citas y las explicaciones de compilación para lograr una programación imperativa escribiendo bloques de tipo pseudocódigo.

Ming-Tang
fuente
1
Suena un poco como Erlang, un lenguaje de programación funcional con tipo dinámico y se suma a eso un lenguaje concurrente bastante único.
Jonas
2

Teniendo en cuenta que los únicos lenguajes que conozco son PHP y JavaScript, y que realmente debería aprender algunos más antes de diseñar un lenguaje:

Sintaxis: piense detenidamente sobre los nombres de las funciones y el orden de los argumentos (es decir, sea menos complicado que PHP).

Características: tiene un conjunto de stringfunciones, que operan en variables como una serie de bytes, pero no entienden el texto, y un conjunto de textfunciones, que entienden muchas codificaciones y pueden operar en UTF-8 y otras cadenas multibyte. (Y tenga controles de sanidad de codificación integrados en el lenguaje, con una función como la text.isValidEncoding(text, encoding)que le indicará si una secuencia de bytes tiene un formato incorrecto y no es seguro tratarla como texto.

Creo que me gusta la idea del tipeo estático fuerte, pero nunca la he usado, por lo que realmente no puedo decirlo.

Trigonometría
fuente
2

Antes de diseñar un lenguaje de programación, encontraría una buena respuesta a la pregunta: ¿por qué necesitamos otro lenguaje de programación más? El Código de Rosetta al momento de escribir esto enumera 344 idiomas. Si ninguno de esos satisface mis necesidades, los detalles específicos de por qué no determinarían el punto de partida (los idiomas que se acercan más) y lo que se agregaría.

Si ganara la lotería y, por alguna razón, no tuviera nada mejor que hacer, comenzaría con Liskell y lo convertiría en un lenguaje completo en lugar de un front-end de GHC, luego haría que FFI sea más fácil (y automatizado) para poder usar cualquier Biblioteca C / C ++.

Larry Coleman
fuente
2

Un buen idioma es un idioma que es:

  • fácil de razonar (sin sintaxis oscura)
  • le permite expresar sus ideas con una distorsión mínima
  • ocultarle los detalles esenciales (optimización / gestión de recursos)
  • fácilmente paralelizable (múltiples núcleos, computación distribuida)

Es bastante difícil convertir esto en una lista de características, pero creo que la programación funcional, a pesar de no sentirse natural , está más cerca de esto que la programación imperativa (especialmente al ocultar los detalles esenciales)

  • Interfaz en C: C es la lengua franca de los lenguajes de programación y la cantidad de bibliotecas desarrolladas en C es asombrosa. Al tener una interfaz fácil (como Python) a C, el lenguaje se beneficia automáticamente de todas esas bibliotecas y también permite enviar tareas pesadas que no podrían optimizarse lo suficiente para un lenguaje cercano al metal.
  • Distribuido : Me gusta la versión de Go en subprocesos múltiples, con rutinas livianas que el tiempo de ejecución distribuye en subprocesos según su actividad. Tal lenguaje alienta al programador a razonar sobre las tareas y aislarlas unas de otras.
  • Recolección de basura : no hace falta decir hoy en día;)
  • Inmutable : mucho más fácil razonar sobre algo que nunca puede mutar, mucho más fácil de implementar computación multiproceso / distribuido también (solo necesita sincronización para manejar la vida útil, que es la tarea del compilador)
  • Lambdas : va con funciones de primera clase, supongo
  • Paso del mensaje : la inmutabilidad significa que no hay mutex, por lo tanto, seguimos la sugerencia de Tony Hoares
  • Módulos : algo similares a los espacios de nombres, pero con una mejor encapsulación
  • Reflexión : el cálculo distribuido requiere la serialización, que debe dejarse al compilador, y la deserialización se logra más fácilmente con alguna forma de reflexión.
  • Escritura fuerte estática : cuanto antes se detecte un error, menos cuesta

Por el momento, el idioma más cercano a esta lista es probablemente Haskell:

  • carece de rutinas: todavía no he visto una forma natural de expresar paralelismo en Haskell (aunque puede ser mi ignorancia ...)
  • tiene una sintaxis oscura: de alguna manera parece que los programadores de Haskell prosperan usando operadores extraños en lugar de palabras. Puede parecer resbaladizo, pero no ayuda mucho entender lo que está sucediendo.
Matthieu M.
fuente
2

A su primera pregunta, "¿cómo lo haría?" - respuesta corta, no lo haría. No tengo suficiente teoría del analizador / compilador para lograrlo. Pero llevo 25 años programando, así que tengo algunas ideas y opiniones que compartir.

En primer lugar, trataría de llegar a un enfoque OOP que le permita crear modelos verdaderamente conectados. Lo que quiero decir con eso es que los modelos son una de las cosas más importantes en casi cualquier tipo de proyecto de programación: siempre es un trabajo duro y una refactorización continua para hacerlo bien, y culpo eso a la falta de conectividad real en OO idiomas.

Permíteme demostrarlo. Digamos que una casa de clase tiene una propiedad de puerta.

var door = house.Door;

Ahora tiene una variable local con una referencia a la instancia de Door.

Pero considere lo que acaba de suceder: acaba de arrancar la puerta de la casa, y ahora está muy feliz de pasar la puerta, y el resto de su código ignora el hecho de que esta puerta está realmente unida a una casa.

Para mí, esto es fundamentalmente incorrecto.

Y sí, lo sé, esto se soluciona "fácilmente" caso por caso, en este caso manteniendo una referencia inversa de cada Puerta de la Casa a la que está conectada actualmente. Por supuesto, esto abre su modelo a errores, ya que ahora es su deber mantener con precisión dos referencias inversas, por lo que hace que las propiedades House.Doors y Door.House sean privadas, y agrega métodos como House.AddDoor (), House.RemoveDoor ( ), Door.SetHouse (), etc., conéctelo todo y realice una prueba unitaria para asegurarse de que realmente funciona.

¿No está empezando a parecer mucho trabajo para modelar una relación tan directa? ¿Mucho código para mantener? ¿Mucho código para refactorizar a medida que el modelo evoluciona?

El problema son los punteros. Todos los lenguajes OO que he visto sufren de manera inherente el hecho de que una referencia de objeto es realmente un puntero, porque eso es lo que usan las computadoras.

Los punteros no son una buena forma de modelar el mundo real. Independientemente del mundo que intente modelar, es casi seguro que cualquier relación en ese mundo será de dos vías. Los punteros apuntan en una sola dirección.

Me gustaría ver un lenguaje donde el modelo de datos fundamental es un gráfico, donde todas las relaciones, por defecto, tienen dos extremos. Es casi seguro que esto proporcionaría un ajuste mucho más natural para modelar el mundo real, que en realidad es lo único para lo que necesitamos computadoras en primer lugar. (eso y los videojuegos).

No tengo idea de cómo se vería la sintaxis para un lenguaje de este tipo, o si incluso se puede expresar con texto. (Me preguntaba si ese lenguaje tendría que ser gráfico, de alguna manera ...)

También me gustaría ver todas las formas de estado accidental eliminado.

Por ejemplo, en el desarrollo web, pasamos mucho tiempo formando datos de bases de datos, en modelos de negocio, en modelos de vista para presentación ... luego, algunos de esos datos se presentan en formularios, lo que en realidad es solo otra transformación. ... y el estado regresa de las publicaciones de formulario, y luego volvemos a dar forma a esos datos y los proyectamos de nuevo en el modelo de vista, por ejemplo, carpetas de modelos de vista y tal ... luego proyectamos desde el modelo de vista de nuevo en el negocio- modelo ... luego usamos mapeadores relacionales de objetos (o trabajo gruñido) para transformar los datos del modelo de vista y proyectarlos en una base de datos relacional ...

¿Esto comienza a sonar redundante? ¿En qué punto durante toda esta locura realmente logramos algo útil? Y por útil quiero decir, algo tangible, algo que el usuario final puede entender y le importa. Al final del día, las horas que dedicó a construir algo que los usuarios pueden entender, en realidad son las únicas horas bien empleadas. Todo lo demás son efectos secundarios.

Quisiera un lenguaje altamente dinámico. El ciclo de escritura / compilación / ejecución es una tediosa pérdida de tiempo. Idealmente, el lenguaje debería descubrir qué cambió y compilar / cargar de forma transparente, en segundo plano, según sea necesario.

Idealmente, ni siquiera debería tener que presionar "ejecutar": las cosas deberían suceder en la pantalla, a medida que realiza cambios, que reflejan inmediatamente los cambios que realiza. El problema con el ciclo de escritura / compilación / ejecución, o incluso para el ciclo de escritura / ejecución más directo, es que estás demasiado desconectado de lo que estás haciendo, para sentirte conectado con nuestro trabajo, nosotros Necesita comentarios inmediatos, resultados instantáneos. ¡Cualquier espera es demasiado larga!

Nuevamente, ni siquiera sé si esto podría lograrse con un IDE tradicional, o si esto requeriría un tipo de interfaz completamente nuevo.

Debería poder usar una combinación de mecanografía débil y fuerte, lo que sea más adecuado para el problema en el que está trabajando.

El estado en general debería ser algo que el lenguaje maneje completamente para usted. ¿Por qué debería necesitar confiar en una base de datos para la persistencia? Idealmente, me gustaría poder especificar simplemente el período de vida de cualquier variable en el modelo: una solicitud web, una sesión, 24 horas, de forma permanente.

¿Por qué tenemos que elegir entre una amplia gama de soluciones de almacenamiento para diferentes medios y plazos de vida? - sin mencionar la transformación y la configuración de los datos para adaptarse a cada medio; caché del navegador, base de datos, memoria, disco, ¡a quién le importa! Los datos son datos. ¡Dónde almacenar sus datos (y por cuánto tiempo) debería ser una elección simple, no una batalla contra los Dioses!

Bueno, buena suerte con eso.

mindplay.dk
fuente
1

Probablemente sea un lenguaje de paradigma múltiple, que soporte lo siguiente:

  • Programación estructurada / procesal
  • Programación orientada a objetos
  • Programación funcional

¿Por qué estos? Orientado a objetos porque es una excelente manera de organizar grandes programas, especialmente para organizar los datos. Estructurado porque no siempre quieres / necesitas eso (OOP), las personas deberían tener opciones. Funcional porque facilita la depuración de los programadores y hace que los programas sean más claros.

Usaría el modelo de Python con bloques sangrados para marcar bloques de código. Es muy claro y agradable de leer.

En realidad, robaría muchas ideas de Python porque Python es un lenguaje muy agradable. Lo tomaría como una declaración y copiaría sus mapas, listas y tuplas.

Ahora, probablemente no tomaría los conceptos dinámicos de Python: por un lado, probablemente sería tipado explícita y estáticamente. Creo que los programas se vuelven más claros con eso. Probablemente todas las variables serían objetos con métodos, entonces podría hacer algo como str.length()obtener la longitud de una cadena. En las definiciones de funciones, debería especificar el tipo de retorno y los tipos de argumentos (que también admiten algún tipo de tipos genéricos).

Volvamos a copiar desde Python ;-). Me encanta su forma de tener argumentos de procedimiento opcionales, así que probablemente lo tenga. Sin embargo, Python no admite la sobrecarga de procedimientos, me gustaría eso.

Veamos las clases, abandonaría la herencia múltiple; a fácil de abusar. Implementaría ámbitos privados y similares y probablemente lo implementaría de la forma en que se hace en C ++. También tendría clases abstractas e interfaces; No creo que Python tenga eso.

Sería compatible con las clases internas, de hecho, me gustaría un lenguaje orientado a objetos muy poderoso.

Probablemente sería interpretado. Es posible hacerlo realmente rápido usando una buena compilación JIT (me gustaría un lenguaje rápido, aunque la productividad del programador sería lo primero) y la compilación es simplemente mala para la productividad en muchas ocasiones. Los idiomas interpretados también promueven la independencia de la plataforma, algo que importa cada vez más para cada día.

Tendría soporte incorporado de Unicode; En estos días la internacionalización es muy importante.

Definitivamente sería basura recolectada. Maldición, odio hacer la administración de la memoria yo mismo; No es bueno para la productividad tampoco.

Finalmente, tendría una buena biblioteca estándar.

Wow, me acabo de dar cuenta de lo mucho que amo Python.

Anto
fuente
¿Por qué Interpreted languages also promote platform independance? Supongo que hay más intérpretes multiplataforma en lugar de compiladores (porcentaje), pero no podría entender por qué esta oración debería ser cierta. Creo que no hay diferencia entre ellos en lo que respecta a las habilidades multiplataforma.
Mahdi
1

En primer lugar, compraría algunos libros sobre compiladores, algunos estándares y tomaría un curso o dos en idiomas y compiladores. Contribuiría con PEP y visitaría las reuniones del comité de estándares de C ++. Contribuiría con parches a los compiladores que uso, con suerte tanto para características como para errores.

Luego regresaría y miraría con horror esta lista que he encontrado ahora, que es de qué direcciones seguiría con un idioma si comenzara en este momento:

  • Funcional , porque actualmente no estoy bien versado en ningún lenguaje funcional y hacer uno sería una excelente manera de aprender uno. En caso de que no siga directamente: todo es constante .
  • Lo llenaría con la mayor cantidad de inferencia de tipos que pudiera, pero con la opción de especificar interfaces explícitamente. No estoy seguro acerca de otros tipos. Esto se duplica ya que todas las funciones son genéricas por defecto.
  • Como habrás adivinado, con Interfaces ; es decir, con tipos que solo ofrecen promesas sobre las operaciones disponibles.
  • Por lo que puedo decir, decir si el idioma está tipeado de forma fuerte o débil no es muy significativo en este caso. Lo llamaría fuertemente tipado, ya que las cosas nunca cambian las interfaces que implementan .
  • Tendría mucho soporte de Diseño por Contrato . Una vez más, tanto como puedo: las condiciones previas y las condiciones posteriores son imprescindibles; No sé cuánto importan los invariantes cuando se trata de programación funcional.
  • Mientras lo hago, echaré un vistazo a los idiomas en los que puedes probar formalmente la corrección y ver si puedo recoger algo a partir de ahí.
  • Salía y escribía una biblioteca de pruebas increíble . Incluso en caso de que no logre hacerlo increíble, al menos pasaré una cantidad considerable de tiempo trabajando en ello, ya que creo que es algo que todo idioma debería tener.
  • En cuanto a la sintaxis, el lenguaje tendría un espacio en blanco significativo y se parecería mucho a Python , o se basaría en Lojban y compartiría gran parte de la gramática y el vocabulario. En el primer caso, haría todo lo posible para que la gramática sea lo más cercana posible a un CFG.
  • No me importaría si las personas que implementaron el lenguaje lo compilan de antemano, lo escriben, lo interpretan, lo cantan en fogatas o les pagan a los universitarios para que lo ejecuten por ellos. Mi propia implementación probablemente comenzaría como un intérprete o un compilador de C, y eventualmente pasaría a un JITter.

Dado que incluso estos puntos bastante amplios probablemente cambiarían rápidamente si comenzara a implementar el lenguaje, creo que no es necesario entrar en más detalles.

Anton Golov
fuente
0

Si tuviera tiempo, diseñaría un lenguaje de programación localizable basado en Scala, por lo que tendría la mayoría de sus características, excepto probablemente el XML. Mi objetivo es crear un idioma que se lea casi naturalmente en idiomas con una estructura diferente al inglés, como el árabe (mi lengua materna). Estoy pensando en las siguientes características:

  • Una #langdirectiva de preprocesador , utilizada para informar al preprocesador del lenguaje humano utilizado para la programación. Por ejemplo: #lang arpermitiría el uso de la palabra en فئةlugar de class, en عرفlugar de def, etc. Las palabras clave específicas del lenguaje humano se definirían en archivos de preprocesador estándar.
  • El preprocesador eliminaría algunas palabras clave opcionales cuyo único propósito es agregar claridad al código. Por ejemplo, eliminaría "está compuesto de" en class MyClass is composed of {convertirse class MyClass {y eliminaría "como" en def MyMethod(x: Int) as {convertirse def MyMethod(x: Int) {. En algunos idiomas (humanos), esto haría que el código sea mucho más fácil de entender, especialmente para los estudiantes.
  • El compilador permitiría el uso de la notación de prefijo para el acceso a la propiedad. Puede que esto no tenga sentido para la mayoría de los hablantes de idiomas latinos, pero para algunos otros idiomas tiene mucho sentido. Por ejemplo, el acceso a la propiedad en árabe normalmente es el prefijo, como en اعرض طول اسم محمد, que es equivalente a print(length(name(Mohammad)))en programación en inglés. (Los paréntesis son para mayor claridad).

Creo que estos cambios mínimos en el preprocesador y el compilador harán que la programación sea mucho más simple para los que no hablan inglés.

Hosam Aly
fuente
55
Microsoft (y algunos otros antes) hicieron versiones localizadas de VBA (Visual Basic para aplicaciones de Office). Fue un desastre. Si bien es bueno para los novatos, los jóvenes y las personas que no hablan inglés leer el código en su lengua materna, es muy difícil compartir el código con personas fuera de su país. En nuestros días en Internet, trabajar de forma aislada no es muy productivo. Si tuviera que confiar solo en fuentes francesas (artículos de blog, libros, etc.) para aprender Scala (como lo hago actualmente), extrañaría mucha información útil. Sin mencionar la dificultad / cantidad de trabajo para localizar las bibliotecas ...
PhiLho
1
@PhiLho: Ciertamente tienes razón. Pero mi propósito principal de crear un lenguaje de este tipo es poder presentar la programación a una audiencia mucho más amplia, incluidos los estudiantes de K-12 y las personas mayores que pueden no ser competentes en inglés. A nivel introductorio, probablemente no necesiten usar bibliotecas externas, y crear envoltorios localizados para algunos pequeños (por ejemplo print) no estaría de más.
Hosam Aly
1
El otro punto es que muchas personas ya usan sus idiomas nativos para los nombres de clases y métodos. No les ayuda que las palabras clave estén en inglés, ni hace una diferencia para otras personas, ya que las palabras clave no son suficientes para entender el código que no está en inglés. Sin embargo, el preprocesador siempre puede reemplazar las palabras clave al inglés y luego a cualquier otro idioma si es necesario.
Hosam Aly