Pregunta

He estado pensando en algunos conceptos que subyacen a un nuevo idioma. Era una especie de juguete en un primer momento, pero ahora me pregunto si podría realmente quieren decir algo. Quiero poner esta cuestión al desbordamiento de la pila para ver si se ha hecho antes, y si puedo conseguir cualquier información, ideas, u otra información.

Empecé a pensar en esto sobre todo después de leer la presentación Jonathan de Edward en la programación declarativa . entonces me mezclé con algunas de mis ideas mayores y lo que he visto en lenguas modernas.

La idea principal detrás de la programación declarativa es "qué" frente a "cómo". Sin embargo, he oído que muchas veces, por lo que parece ser casi siempre como la palabra "interesante", donde en realidad no se dice nada, lo cual es frustrante.

En la versión de Jonathan Edwards, sin embargo, que comenzó haciendo hincapié en evaluación perezosa . Esto tiene algunas consecuencias interesantes, a saber programación funcional reactivo (FRP) . Aquí es un ejemplo de FRP con la animación (utilizando una sintaxis que hice up):

x as time * 2 // time is some value representing the current time
y as x + (2 * 500)

new Point(x, y)

Así que aquí los valores sólo cambia de forma automática si el cambio de entradas. En una de mis favoritas idiomas, D , había una distinción entre "pura" y funciones "impuros". Una pura función es una función que no tenía ninguna relación con el mundo exterior y otras funciones puras utilizadas solamente. De lo contrario sería impura. El punto es que siempre se puede confiar en una pura función para devolver el mismo valor para argumentos dados.

supongo que un principio similar se aplica aquí transitiva. Nuestra impureza es time. Todo tocado por time, siendo x, por lo tanto y, y por lo tanto new Point(x, y) son impuros. Sin embargo, el aviso (2 * 500) es puro. Así que ya ves esto le dice al compilador dónde están sus límites. Pienso en ello como la simplificación de una expresión matemática con variables:

(x ^ 2) + 3x + 5
(4 ^ 2) + 3x + 5 = 16 + 3x + 5 = 21 + 3x = 3(7 + x)

Al decirle al compilador lo que es puro y lo que no lo es, podemos simplificar nuestros programas mucho. Otro punto es datos ansiosos o mutables. Jonathan Edwards del reconocido la entrada como mutable y con ganas, pero la salida como funcional y perezoso. Básicamente, dado nueva entrada, el programa define un cambio de estado atómico y la salida sería simplemente una función del estado actual . Si desea ver por qué esto puede ser importante, ver la presentación. Entrada es impura. La evaluación perezosa ayuda a definir el cambio de estado atómico. Vamos a echar un vistazo a cómo un programa se escribiría de procedimiento:

void main ()
{
    String input = "";

    writeln("Hello, world!");
    writeln("What's your name? ");

    input = readln();

    writeln("Hello, %s!", input);
    writeln("What's your friends name? ");

    input = readln();

    writeln("Hello to you too, %s!", input);
}

Aquí la palabra clave bind dice que el siguiente código se ejecuta si begin cambia. La palabra clave mutable dice que la entrada no es perezoso, pero con muchas ganas. Ahora vamos a ver cómo un "cambio de estado atómico" podría representarla.

program:
    mutable step := 0

    bind begin:
        writeln("Hello, world!")
        writeln("What's your name? ")
        ++step

    bind readln() as input when step = 1:
        writeln("Hello, %s!", input)
        writeln("What's your friends name? ")
        ++step

    bind readln() as input when step = 2:
        writeln("Hello to you too, %s!", input)

Ahora, aquí vemos algo que se podría hacer más fácil y más fácil de leer, para el programador. En primer lugar es la variable step feo y cómo debemos incrementar y poner a prueba cada vez. He aquí un ejemplo de lo que una nueva y mejorada versión podría ser:

program:
    bind begin:
        writeln("Hello, world!")
        writeln("What's your name? ")

    bind readln() as input:
        writeln("Hello, %s!", input)
        writeln("What's your friends name? ")
        yield // This just means the program jumps to here instead of at the beginning
        writeln("Hello to you too, %s!", input)
        halt

Así está mejor. No es perfecto, sin embargo. Pero si supiera la respuesta perfecta, yo no estaría aquí, ¿verdad?

Aquí hay un mejor ejemplo, usando un motor de juego:

class VideoManager:
    bind begin: // Basically a static constructor, will only be called once and at the beginning
        // Some video set up stuff

    bind end: // Basically a static destructor
        // Some video shut down stuff

class Input:
    quitEvent     as handle // A handle is an empty value, but can be updated so code that's bound to it changes.
    keyboardEvent as handle(KeyboardEvent) // This handle does return a value though
    mouseEvent    as handle(MouseEvent)

    // Some other code manages actually updating the handles.

class Sprite:
    mutable x := 0
    mutable y := 0

    bind this.videoManager.updateFrame:
        // Draw this sprite

class FieldState:
    input  as new Input
    player as new Sprite

    bind input.quitEvent:
        halt

    bind input.keyboardEvent as e:
        if e.type = LEFT:
            this.player.x -= 2
        else if e.type = RIGHT:
            this.player.x += 2
        else if e.type = UP:
            this.player.y -= 2
        else if e.type = DOWN:
            this.player.y += 2

Me gusta que esto no requiere devoluciones de llamada, eventos o bucles o incluso nada, y los hilos son obvias. Es más fácil decir lo que está pasando, y no es sólo el pitón similar a la sintaxis. Creo que es el tipo de cosas como cuando los desarrolladores de lenguaje se dieron cuenta de que sólo había unas pocas cosas que las personas estaban usando etiquetas y Goto'como: saltos condicionales y bucles. Así que construyeron if-then-else, while y para a los idiomas, las etiquetas y de Goto se ha hecho obsoleto, y los compiladores, así como las personas podrían decir lo que estaba pasando. La mayor parte de lo que usamos proviene de ese proceso.

Volviendo a las discusiones, lo bueno de esto es que las discusiones son mucho más flexibles. Si el compilador es libre de hacer lo que quiere, porque hemos llegado más cerca de lo que queremos decir, no como queremos que se haga. Por lo tanto, el compilador puede tomar ventaja de varios núcleos y procesadores distribuidos, y aún así compensar las plataformas sin un buen soporte roscado.

Hay una última cosa que me gustaría mencionar. Y ese es mi punto de vista sobre las plantillas. Esta fue una especie de huevo conceptual que comenzó a desarrollar como empecé programación (hace alrededor de 2 años, en realidad), y más tarde comenzó a agrietarse. Básicamente fue el principio de abstracción, sino que se extendía más allá de las clases y objetos.

Tiene que ver con la forma en que yo percibía una función. Por ejemplo:

int add (int a, int b)
{
    return a + b;
}

De acuerdo, add devuelve un int, pero lo que era ¿verdad? En cierto modo se sentía como un int a punto de ocurrir. Como un rompecabezas sin algunas piezas. Había posibilidades limitadas, y sólo ciertas piezas encajan, pero cuando te estaban haciendo que tenía un producto terminado que usted podría entonces utilizar en otro lugar. Esto es, como he dicho, el principio de abstracción. Estos son algunos ejemplos de lo que creo que están abstracción + piezas que faltan -> relaciones concretas:

  • Función + argumentos -> valor
  • clase abstracta + métodos -> class
  • valores de clase + instancia -> objeto
  • plantilla + argumentos -> función o clase
  • programa + entrada + estado -> salida

Son todos muy relacionado. Parece que esto podría ser aprovechada. ¿Pero cómo? Una vez más, es por eso que esta es una pregunta. Pero la evaluación perezosa es interesante aquí, ya que se puede pasar algo con sus piezas siguen desaparecidas a otra cosa. Para el compilador es sobre todo una cuestión de eliminación de referencias a nombres a las impurezas. Al igual que mi ejemplo anterior:

(x ^ 2) + 3x + 5
(4 ^ 2) + 3x + 5 = 16 + 3x + 5 = 21 + 3x = 3(7 + x)

Los más piezas le dan al compilador, más se puede terminarlo y reducir el programa a su núcleo esencial. Y la función add anterior se resuelve en tiempo de compilación, de forma automática, ya que no se basa en recursos externos. Incluso muchas de las clases y los objetos podrían ser resueltas, y enormes porciones de programas, dependiendo de qué tan inteligente es el compilador.

Eso es todo por ahora. Si usted ha visto ejemplos de estas cosas ya hechas, me gustaría ver. Y si usted tiene alguna idea, innovación, recursos, o retroalimentación, lo agradecería también.

¿Fue útil?

Solución

definitivamente querría echar un vistazo a la Haskell lenguaje de programación.

Haskell es muy declarativa, perezoso-evaluación está incorporada y existe incluso bibliotecas de programación funcionales reactivos. Pero sobre todo, Haskell es puramente funcional , es decir, todo, realmente todo, es pura .

Así que la pregunta es ¿Cómo trata Haskell con las impurezas necesarias que surgen a través de cualquier IO.

Los ajustes de respuesta bastante bien a los pensamientos que presentan. Haskell utiliza una construcción matemática llamado mónadas que representan básicamente un cálculo producir algún valor junto con una función bind (>>= como un operador infijo), que las secuencias de tales cálculos.

Así que tomemos algunos ejemplos IO: Leer una línea de salida y su nombre ... Incluso IO es puro, por lo que no se puede manejar algo. En su lugar, se genera una mayor IO cálculo

do
    putStr "Enter your name: "
    name <- getLine
    putStrLn ("Hello " ++ name)

Parece bastante imprescindible, pero bajo el capó, es sólo la sintaxis de

(putStr "Enter your name: ") >>
(getLine >>= \name ->
 putStrLn ("Hello " ++ name))

Ahora se puede definir este bind / >>= para tipos arbitrarios de cálculos , en cualquier forma que desee. Así que, de hecho, todo lo que se habló sobre se puede implementar de esta manera -. Incluso FRP

Solo trata de buscar las mónadas o Haskell aquí en Stackoverflow; ha habido muchas preguntas a este tema. Y después de todo, sigue siendo de tipo comprobado todo y por lo tanto la corrección puede ser aplicada por el compilador.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top