2009-06-02 9 views
13

Actualmente estoy incorporando Lua y usándolo como un archivo de configuración inteligente glorificado. Sin embargo, creo que me falta algo, ya que la gente se entusiasma con los usos de Lua.Ejemplo de uso donde Lua se adapta mucho mejor que C/C++

Por ejemplo, puedo explicar fácilmente por qué es posible utilizar secuencias de comandos shell en lugar de C, mostrando este ejemplo (la verdad, impulso expresión regular es una exageración):

#include <dirent.h> 
#include <stdio.h> 
#include <boost/regex.hpp> 

int main(int argc, char * argv[]) { 
    DIR   *d; 
    struct dirent *dir; 
    boost::regex re(".*\\.cpp$"); 
    if (argc==2) d = opendir(argv[1]); else d = opendir("."); 
if (d) { 
    while ((dir = readdir(d)) != NULL) { 
      if (boost::regex_match(dir->d_name, re)) printf("%s\n", dir->d_name); 
    } 

    closedir(d); 
} 

return(0); 

y compararlo con:

for foo in *.cpp; do echo $foo; done; 

¿Hay algún ejemplo que puedas dar en Lua que pueda hacer que 'haga clic' en mi nombre?

EDIT: Quizás mi problema es que aún no conozco a Lua lo suficiente como para utilizarlo con fluidez ya que me es más fácil escribir el código C.

Edit2:

Un ejemplo es un programa factorial juguete en C++ y Lua:

#include <iostream> 

int fact (int n){ 
    if (n==0) return 1; else 
    return (n*fact(n-1)); 
} 

int main(){ 
    int input; 
    using namespace std; 
    cout << "Enter a number: " ; 
    cin >> input; 
    cout << "factorial: " << fact(input) << endl; 
    return 0; 
} 

Lua:

function fact (n) 
    if n==0 then 
     return 1 
    else 
     return n * (fact(n-1)) 
    end 
end 

print ("enter a number") 
a = io.read("*number") 
print ("Factorial: ",fact(a)) 

Aquí, los programas se parecen, pero hay claramente algunas cruft en las declaraciones include, namespace y main() de las que puede deshacerse. También elimine declaraciones de variables y tipeo fuerte.

¿Ahora las personas dicen que esta es la ventaja que se suma a un programa más grande, o hay más que eso? Esto no se destaca de la misma manera que el ejemplo de bash.

+0

Duplicado de http://stackoverflow.com/questions/591523/when-is-it-good-to-use-embedded-script-language-like-lua? –

+0

Aprender otros lenguajes de programación te hará un mejor programador. Aprende a pensar diferente, incluso en C. – 0x6adb015

+0

El duplicado cercano se está acercando al mismo tipo de pregunta desde una dirección diferente. Los enlaces cruzados son buenos, pero yo no veo esto como un duplicado "exacto". – RBerteig

Respuesta

10

El uso de un lenguaje de scripting como Lua tiene muchos otros beneficios.

Un par de ventajas a Lua vs C++:

  • A menudo es más corto en términos de tiempo de desarrollo debido a la naturaleza de alto nivel, como en el ejemplo.
  • No es necesario volver a compilar para cambiar el comportamiento.
  • El comportamiento se puede cambiar en máquinas sin desarrollo.
  • Los prototipos son muy rápidos y fáciles, ya que puede ajustar la lógica en tiempo de ejecución.
+3

... la funcionalidad puede ser modificada y aumentada/mejorada por no desarrolladores – none

+1

@none: Buen punto, pero todavía considero a Lua un lenguaje de programación en sí mismo, por lo que IMO, todavía necesita un "desarrollador" (aunque quizás un menos experimentado). –

3

Intenta implementar una tabla de Lua en C/C++, verás la fuerza de Lua allí mismo.

En Lua:

a["index"] = "value" 

En C, comience leyendo acerca lista enlazada ...

C++ STL puede ayudar, pero va a ser mucho más detallado de lo Lua.

También, Lua hace un gran pegamento. Es muy fácil (en mi humilde opinión) interactuar con C.

+0

Gracias. ¿Has usado Qt's QList?Me pregunto si eso ofrece algo comparable. – bugmenot77

+0

No. Estoy seguro de que hay algo que ofrece cosas similares, ¿pero tan simple como Lua? – 0x6adb015

+3

¿Qué pasa con std :: map en C++? – bdonlan

3

No sé si hago 'clic' para usted, pero lo intentaré.

Una de las ventajas de incrustar Lua es que no solo puede usarlo como un archivo de configuración sino que realmente ofrece sus interfaces C/C++ a lua y 'script' su uso a través del lenguaje de escritura Lua.

Si desea cambiar el comportamiento/lógica de su aplicación, solo tiene que cambiar el código en la secuencia de comandos Lua sin la necesidad de volver a compilar toda la aplicación.

Los usos principales son lógicas de juego como las máquinas de estado AI oder, donde un tiempo de ida y vuelta rápido desde el cambio hasta el juego es esencial para desarrollar el juego.

Por supuesto, la lógica principal debe estar presente en el script Lua, no dentro del código C/C++, para ser utilizado efectivamente.

+0

Gracias. Probablemente exageré un poco y uso Lua para implementar AI en la lógica del juego. Al hacer esto, me encontré con problemas sobre si las cosas deberían implementarse en C, Lua o alguna combinación. – bugmenot77

1

Para un ejemplo de donde Lua se ajusta mejor que C++ mira la distribución de scripts. Mush Client ofrece Lua como lenguaje de scripting. Como se muestra en el enlace anterior, puede hacer mucho con Lua para extender el programa. A diferencia de C++, aunque Lua no tiene que compilarse y puede restringirse. Por ejemplo, puede areguarar Lua para que no pueda acceder al sistema de archivos. Esto significa que si obtiene un script de otra persona, no podrá destruir sus datos, ya que no puede escribir en el disco.

+0

Gracias. Puedo ver totalmente el caso en el que Lua está incrustado o usado para ampliar, agregar complementos, secuencias de comandos, etc. Pero también escucho que las personas cambian de C a Lua y solo escriben C 'módulos' cuando la velocidad es un factor. Sospecho que tal vez no soy lo suficientemente fluido en Lua y si fuera así, podría escribir más rápido/más fácil en Lua que C. – bugmenot77

+0

C++/C también puede ser limitado y restringido. Mira NaCl. – Alice

2

La programación solo en C puede ser una tarea muy tediosa y redundante, esto sin duda se aplica en comparación con los lenguajes de alto nivel más abstractos.

En este sentido, puede comenzar y terminar cosas mucho más rápido que hacerlo directamente en C, esto es porque muchas cosas que necesitan configurarse, hacerse y limpiarse explícita y manualmente en C, a menudo son implícitamente y manejado automáticamente por un lenguaje de scripts como Lua (por ejemplo, imagina administración de memoria).

De forma similar, muchas estructuras de datos y algoritmos más abstractos son proporcionados directamente por tales lenguajes de alto nivel, por lo que no tiene que reinventar la rueda y volver a implementarla, si todo lo que necesita es un contenedor estándar (pensar en la lista vinculada, árbol, mapa, etc.).

Por lo tanto, puede obtener un ROI bastante bueno cuando utiliza un lenguaje de scripting bastante abstracto como Lua o incluso Python, especialmente si el idioma correspondiente viene con una buena biblioteca de funciones básicas.

Por lo tanto, la creación de scripts es realmente ideal para generar prototipos de ideas y proyectos, porque es cuando debe ser capaz de concentrarse en su esfuerzo, en lugar de todas las redundancias mecánicas que son idénticas para la mayoría de los proyectos.

Una vez que haya completado un prototipo básico, siempre podrá ver cómo mejorarlo y optimizarlo aún más, posiblemente volver a implementar la funcionalidad de clave esencial en el espacio C, para mejorar el rendimiento en el tiempo de ejecución.

+0

Gracias. ¿Te refieres a las cosas como se muestra en mi segunda edición? – bugmenot77

1

Las principales ventajas de Lua como un lenguaje de programación (aparte de la incrustación) son

  • , tabla de dispersión eficiente de gran alcance como la estructura de datos principal
  • cadena de procesamiento de biblioteca con un excelente equilibrio entre complejidad y poder expresivo
  • Funciones de primera clase y genérico for bucle
  • Gestión de memoria automática !!

Es difícil encontrar un pequeño ejemplo que ilustre todo esto.Tengo 191 scripts Lua en mi directorio ~/bin; Aquí hay una que toma la salida de pstotext y se une a las líneas que terminan en un guión:

local function printf(...) return io.stdout:write(string.format(...)) end 
local function eprintf(...) return io.stderr:write(string.format(...)) end 

local strfind, strlen = string.find, string.len 

function joined_lines(f) 
    return coroutine.wrap(function() 
          local s = '' 
          for l in f:lines() do 
          s = s .. l 
          local n = strlen(s) 
          if strfind(s, '[%-\173]$', n-1) then 
           s = string.sub(s, 1, n-1) 
          else 
           coroutine.yield(s) 
           s = '' 
          end 
          end 
         end) 
end 

-- printf('hyphen is %q; index is %d\n', '­', string.byte('­')) 

for _, f in ipairs(arg) do 
    for l in joined_lines(io.popen('pstotext ' .. f, 'r')) do 
    printf('%s\n', l) 
    end 
end 

Este ejemplo muestra varias características de ventaja, pero no hace nada interesante con tablas.

Aquí hay un fragmento breve de un programa de indexación de Palabras clave en contexto, que recupera el contexto de una tabla y formatea la palabra clave en contexto. En este ejemplo se hace un uso más amplio de funciones anidadas y muestra un poco más de la mesa y la cadena de cosas:

local function showpos(word, pos, lw, start) 
    -- word is the key word in which the search string occurs 
    -- pos is its position in the document 
    -- lw is the width of the context around the word 
    -- start is the position of the search string within the word 
    local shift = (start or 1) - 1 -- number of cols to shift word to align keys 
    lw = lw - shift -- 'left width' 
    local rw = cols - 20 - 3 - lw - string.len(words[pos]) -- right width 
    local data = assert(map:lookup(pos)[1], "no map info for position") 
    -- data == source of this word 
    local function range(lo, hi) 
    -- return words in the range lo..hi, but only in the current section 
    if lo < data.lo then lo = data.lo end 
    if hi > data.hi then hi = data.hi end 
    local t = { } 
    for i = lo, hi-1 do table.insert(t, words[i]) end 
    return table.concat(t, ' ') 
    end 
    -- grab words on left and right, 
    -- then format and print as many as we have room for 
    local left = range(pos-width, pos) 
    local right = range(pos+1, pos+1+width) 
    local fmt = string.format('[%%-18.18s] %%%d.%ds %%s %%-%d.%ds\n', 
          lw, lw, rw, rw) 
    printf(fmt, data.title, string.sub(left, -lw), word, right) 
end 
+1

std :: unordered_map, std :: string, C++ 11 para bucles y lambdas, y RAII y std :: shared_ptr son tan rápidos y fáciles de usar como las alternativas de lua. – Alice

4

Los lenguajes de script reducir el esfuerzo necesario para construir interfaces gráficas de usuario complejas que de otro modo requieren una gran cantidad de pegamento marco y la repetición de código. Varios kits de herramientas GUI están disponibles con enlaces Lua, incluidos wxWidgets y IUP toolkit.

En ambos enlaces, los valores de función de primera clase y los cierres completos hacen que las devoluciones de llamada de los eventos sean fáciles de codificar y fáciles de usar.

Una aplicación grande que utiliza Lua en su núcleo (como Adobe Photoshop Lightroom) tiene un programa exterior C/C++ que aloja el intérprete Lua y proporciona acceso a sus funciones principales registrando funciones C con ese intérprete. Por lo general, implementa funciones principales de cálculo intensivo en las funciones C, pero deja el flujo general, la operación e incluso el diseño de la GUI en los scripts de Lua.

He encontrado en mis propios proyectos que a menudo es el caso que el intérprete independiente de Lua (lua.exe o wlua.exe) es suficiente para la aplicación externa cuando se combina con IUP cargado en tiempo de ejecución junto con uno o dos módulos Lua personalizados basados ​​en DLL codificados en C que implementan características que requieren ese nivel de rendimiento o características que se implementan a través de otras bibliotecas C-invocables.

Los puntos importantes para mis proyectos han incluido:

  • llamadas de cola verdaderos permiten una fácil expresión de máquinas de estados finitos.
  • Administración de memoria recolectada.
  • Funciones anónimas, cierres, valores de función de primera clase.
  • Tablas hash.
  • Bastante suficiente biblioteca de cadenas.
  • Userdata amplía el recolector de basura a las asignaciones del lado C.
  • Las metatablas permiten una rica variedad de técnicas orientadas a objetos y funcionales.
  • C API pequeña pero suficientemente potente.
  • Bueno documentation, con código abierto como copia de seguridad.
  • Buena compatibilidad con el usuario a través del mailing list y wiki.
  • Potentes módulos como un analizador PEG disponible de los autores y del community.

Uno de mis ejemplos favoritos para citar es una plantilla de prueba que construí para un sistema integrado que requería alrededor de 1000 líneas de Lua y 1000 líneas de C, corría bajo lua.exe y usaba IUP para presentar Windows completo GUI. La primera versión se estaba ejecutando en aproximadamente un día.En C++ con MFC, habría sido al menos una semana de trabajo y muchos miles de líneas de código.

+0

Las llamadas de cola siempre se pueden convertir en iteración, RAII significa que no tiene basura, C++ 11 lambdas, 'std :: unordered_map',' std :: string' y 'stlport :: rope', no hay basura,' boost :: mixins', y 'boost :: spirit'. Nada de lo que ha dicho muestra que Lua es mejor que C++, y le garantizo que podría haber escrito su programa usando QT en menos tiempo de lo que tardó en escribirlo en Lua. – Alice

1

Uso un motor de juego llamado Love2D que usa Lua para escribir juegos. Todas las llamadas al sistema y el levantamiento de pesas se realizan en un programa C que lee una secuencia de comandos Lua.

Al escribir un juego en C o C++, te encuentras tratando de trabajar con las sutilezas del sistema en lugar de simplemente implementar tus ideas.

Lua permite la codificación "limpia" de estilo sucio.

He aquí un ejemplo de un objeto de juego escrito en Lua puro:

local GameObj = {}    -- {} is an empty table 
GameObj.position = {x=0,y=0} 
GameObj.components = {} 

function GameObject:update() 
    for i,v in ipairs(self.components) do -- For each component... 
     v:update(self)      -- call the update method 
    end 
end 

para crear una instancia:

myObj = setmetatable({},{__index=GameObj}) 
-- tables can have a meta table which define certain behaviours 
-- __index defines a table that is referred to when the table 
-- itself doesn't have the requested index 

Vamos a definir un componente, ¿qué hay de control del teclado? Suponiendo que tenemos un objeto que hace de entrada para nosotros (que C-lado serían suministrados)

KeyBoardControl = {} 
function KeyBoardControl:update(caller) 
    -- assuming "Input", an object that has a isKeyDown function that returns 
    -- a boolean 
    if Input.isKeyDown("left") then 
     caller.position.x = caller.position.x-1 
    end 
    if Input.isKeyDown("right") then 
     caller.position.x = caller.position.x+1 
    end 
    if Input.isKeyDown("up") then 
     caller.position.y = caller.position.y-1 
    end 
    if Input.isKeyDown("down") then 
     caller.position.y = caller.position.y+1 
    end 
end 
--Instantiate a new KeyboardControl and add it to our components 
table.insert(myObj.components,setmetatable({},{__index=KeyboardControl}) 

Ahora cuando llamamos myObj: update() se comprobará entradas y moverlo

Digámosnos 'll estar usando un montón de este tipo de GameObj con un KeyboardControl, podemos crear una instancia de un prototipo KeyObj y el uso que al igual que un objeto heredado:

KeyObj = setmetatable({}, {__index = GameObj}) 
table.insert(KeyObj.components,setmetatable({}, {__index = KeyboardControl})  

myKeyObjs = {} 

for i=1,10 do 
    myKeyObjs[i] = setmetatable({}, {__index = KeyObj}) 
end 

Ahora tenemos una mesa de KeyObj que podemos jugar. Aquí podemos ver cómo Lua nos proporciona un sistema de objetos flexible, potente y fácil de extender que nos permite estructurar nuestro programa de acuerdo con el problema que estamos tratando de resolver, en lugar de tener que doblar el problema para encajar en nuestro idioma.

Además, Lua tiene algunas otras características agradables como funciones como tipos de primera clase, lo que permite la programación lambda, funciones anónimas y otras cosas que generalmente tienen maestros comp-sci sonriendo ligeramente.

1

LUA tiene closures, y cierra la roca. Para example:

function newCounter() 
    local i = 0 
    return function() -- anonymous function 
      i = i + 1 
      return i 
     end 
end 

c1 = newCounter() 
print(c1()) --> 1 
print(c1()) --> 2 

Puede crear una función y pasarla. A veces es más útil que crear clases separadas e instanciarlas.

+4

Lo mismo ocurre con C++. Ver C++ 11 y C++ 14 lambdas. – Alice

Cuestiones relacionadas