it-swarm-es.com

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

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.

41
Chinmay Kanchi
  • Definitivamente creo que los lenguajes de programación funcional 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. Por lo tanto, 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 mensaje que pasa , con mensajes inmutables. Enviar y olvidar. Como en el modelo de actor. Ver Programación orientada a objetos: ¿El camino equivocado? =

  • Creo que sería bueno tener escritura estática , por lo que los errores se detectan antes en el ciclo de desarrollo. Pero usaría 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. Ver Learn You A Haskell for Great Good

  • 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 Programación reactiva funcional .

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

55
Jonas

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 escritura

La característica número uno que me gustaría en un idioma es la escritura estática con opcional escritura dinámica. 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á tipeado estáticamente de manera implícita, independientemente de si el idioma hace o no la distinción. Sin embargo, hay varios casos de uso en los que 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 de optimización tendrá un mucho más fácil de optimizar código estáticamente tipado, y El código escrito dinámicamente podría simplemente dejarse como está.

. Cierres

El lenguaje debe soportar 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 integrados

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

  • Un int tipo de datos o tipos. Si solo hay un tipo int, debe tener un rango ilimitado. Si hay más, debe 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 solo tipo binario incorporado float, que es equivalente a un IEEE 754 double
  • Un tipo mutable list que se implementa como una lista doblemente vinculada o como un bloque de memoria contigua que contiene punteros a cada elemento
  • Un tipo list inmutable que actúa como una matriz pero cuyo tamaño no se puede cambiar después de la creación
  • Tipos mutables e inmutables string, siendo el valor predeterminado inmutable.
  • Un tipo map o dict que es mutable y contiene claves inmutables y valores mutables y/o inmutables.
  • Los tipos de colección integrados deben ser de tipo homogéneo por defecto, pero pueden ser vartyped si es necesario
  • Un tipo boolean
  • Un tipo null o none que se puede asignar a una variable de cualquier tipo.
  • Tipos mutables e inmutables set
  • Un tipo decimal que implementa variables decimales de coma flotante
  • Un tipo fixed, que implementa un número de punto fijo

Los tipos decimal, float y fixed deben compartir la misma interfaz pública exacta (ya sea a través de herencia o escritura de pato), lo que les permite pasar y regresar de forma transparente desde las funciones. El tipo padre podría llamarse 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 la aritmética de punteros. Los punteros solo se pueden escribir de forma estática (para evitar la pesadilla que es un void*). Los punteros vartype 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. Asamblea 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 se pueden relegar 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 inseguro bloques 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.

22
Chinmay Kanchi

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

  • Un potente sistema de tipo estático con cierto soporte para la escritura 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, sino algo así como Ioke/Seph.)
7
missingfaktor

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

(Excepto, por supuesto, que la mía habría sido menos pensada y más aficionada).

No me importa mucho si está compilada o interpretada, así que no necesito justificar esa parte.

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 me preocupo demasiado por los detalles de la sintaxis, por lo que no necesito justificarlo en detalle, excepto que no quiero que sea tan detallado como Visual Basic.

¿Qué más quieres que justifique?

6
Timwi

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


LISP como sintaxis

Estilo LISP

Profesionales :

  • 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

Profesionales :

  • 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

Profesionales :

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

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

Profesionales :

  • 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

Profesionales :

  • 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 dispositivos 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)

Profesionales :

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

5
Joe D

Consejos del compilador

Estoy hablando fuera 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. Sugerencias 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 vago, 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.

3
Mark Canlas

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. El Java API es bueno así, y C # /. NET es bastante bueno. 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 respaldados, bien documentados 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 ++)
3
Fishtoaster

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? Código de Rosetta en el momento de escribir esto enumera 344 idiomas. Si ninguno de ellos 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 que pueda usar cualquier Biblioteca C/C++.

2
Larry Coleman

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 en 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 toma de Go en subprocesos múltiples, con rutinas livianas que el tiempo de ejecución distribuye en subprocesos dependiendo de su actividad. Tal lenguaje alienta al programador a razonar sobre las tareas y aislarlas unas de otras.
  • Recolección de basura: no hace falta decirlo hoy en día;)
  • Inmutable: mucho más fácil de 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
  • Mensaje pasando: la inmutabilidad significa que no hay mutex, por lo tanto, seguimos la sugerencia de Tony Hoares
  • Módulos: algo similar a los espacios de nombres, pero con una mejor encapsulación
  • Reflexión: el cálculo distribuido requiere 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 detecta un error, menos cuesta

Por el momento, el lenguaje más cercano a esta lista es probablemente Haskell, sin embargo:

  • 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.
2
Matthieu M.

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 encontrar un enfoque OOP) que te 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 pesado y una refactorización continua para hacerlo bien, y lo culpo por 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 evoluciona el modelo?

El problema son los punteros. Cada OO lenguaje que he visto, sufre inherentemente del 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. Esto casi con certeza 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 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 negocios, 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 reformamos esos datos y los proyectamos nuevamente en el modelo de vista, por ejemplo enlazadores de modelos de vista y tal ... luego proyectamos desde el modelo de vista nuevamente al modelo de negocio ... luego usamos mapeadores relacionales de objetos (o trabajo gruñido) para transformar los datos del modelo de vista y proyectarlo 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!

Una vez más, 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 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.

2
mindplay.dk

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: Piensa cuidadosamente sobre los nombres de las funciones y el orden de los argumentos (es decir, ser menos desordenado que PHP).

Características: Tiene un conjunto de funciones string, que operan en variables como una serie de bytes, pero no entienden el texto, y un conjunto de funciones text, que comprenden muchas codificaciones y pueden funcionar en UTF-8 y otras cadenas multibyte. (Y tenga controles de sanidad de codificación integrados en el lenguaje, con una función como text.isValidEncoding(text, encoding) que le dirá si una secuencia de bytes está mal formada y no es segura 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.

2
TRiG

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 sentencias 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 val Comienza una función curry con dos argumentos, val.Type Es lo mismo que Type[val], !! Se convierte en booleano, y booleano se puede aplicar, entonces val y def are after it.

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

y en greet, usó name<(default "world") y hasType Str>, significa que el patrón default "world" se usará y se unirá a name. El patrón predeterminado especifica un valor predeterminado. and es otro patrón que encadena dos patrones juntos. el patrón default no puede fallar mientras que hasType puede 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 citas y explicaciones comp para lograr una programación imperativa al escribir bloques de tipo pseudocódigo.

2
Ming-Tang

Probablemente sería un lenguaje de paradigmas múltiples, que admite 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.

Robaría muchas ideas de Python en realidad 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() para obtener la longitud de una cadena. En las definiciones de funciones, tendría que 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 que tenga argumentos de procedimiento opcionales, por lo que probablemente lo tenga. Python sin embargo 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 Unicode; En estos días la internacionalización es muy importante.

Definitivamente sería basura recolectada. Maldita sea, odio hacer la gestió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.

1
Anto

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 PEP sy 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 ahora:

  • 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 tanta inferencia de tipos como 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 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 demostrar formalmente la corrección y ver si puedo recoger algo a partir de ahí.
  • Salía y escribía una impresionante biblioteca de pruebas . 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 espacios en blanco significativos y se parecería mucho a Python , o sería basado en Lojban y compartiendo 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 JITAN, lo interpretan, lo cantan en fogatas , o le pagan a los universitarios para que lo ejecuten para ellos Mi propia implementación probablemente comenzaría como un intérprete o un compilador de C, y eventualmente pasaría a un JITter.

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

1
Anton Golov

Si tuviera tiempo, diseñaría un lenguaje de programación localizable que se basa en Scala, por lo que tendría la mayoría de sus características, excepto probablemente para 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 directiva de preprocesador #lang, Utilizada para informar al preprocesador del lenguaje humano utilizado para la programación. Por ejemplo: #lang ar Permitiría el uso de la palabra فئة En lugar de class, عرف En lugar de def, y así sucesivamente. 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 { Para convertirse en class MyClass {, Y eliminaría "como" en def MyMethod(x: Int) as { para convertirse en 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 notación de prefijo para el acceso a la propiedad. Esto puede no tener 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 es normalmente un prefijo, como en اعرض طول اسم محمد, Que es equivalente a print(length(name(Mohammad))) en programación-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.

0
Hosam Aly