Ir al contenido


Foto

Como funciona un Funcion


  • Por favor identifícate para responder
39 respuestas en este tema

#21 Fenareth

Fenareth

    Advanced Member

  • Administrador
  • 3.486 mensajes
  • LocationMexico City

Escrito 11 diciembre 2008 - 08:08

Jejeje, qué obsesión de preguntar cosas en las que si puedo ayudar justo cuando no estoy  :p  :

Esperaré pacientemente  *-)  :D
  • 0

#22 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 11 diciembre 2008 - 08:14

Hola
Que bueno, eso si me da mucha mas claridad en el asunto.
Hombre, Maestro, como me ayudas.
Gracias amigo.
Saludos


Vamos amigo, eso de Maestro me queda grande, pero si insistes me puedes decir maistro :D :D :D

Jejeje, qué obsesión de preguntar cosas en las que si puedo ayudar justo cuando no estoy  :p  :

Esperaré pacientemente  *-)  :D


Pues que esperas para hacer tu comentario amiguita, yo nomas contesto a lo loco y ni se de que estamos hablando jajajaja

Salud OS
  • 0

#23 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 11 diciembre 2008 - 08:18

Dentro de una función puedes hacer lo que se te ocurra, incluso llamar a otras funciones y/o procedimientos.

Imagina que a un problema lo partes en pedacitoss más chicos y ahora cada parte resuelve algún hecho concreto del problema. De este modo el problema general se divide en porciones más simples y fáciles de entender.

Ese es uno de los propósitos de las funciones y procedimientos: concentrar en una rutina (sentencias) alguna funcionalidad, o utilidad de modo que con invocar a dicha función o procedimiento consigamos armar un problema mayor.

Otra cosa que sería muy útil mencionar y aclarar que entre los parámetros de entrada podemos encontrarnos con algo como esto:



delphi
  1. function Nombre(dato1, datoN: tipo; var datoM: tipo_M): tipo;
  2. ...



Ese parámetro datoM es tanto como de entrada como de salida. Se trata de un parámetro especial: nos permite que una función nos regrese otro valor más. Los procedimientos no regresan ningún valor, pero gracias a éste tipo de parámetro es posible devolver un valor.
Este parámetro por lo general es para "notificar" que algo ha cambiado dentro de la sentencia. Se lo suele emplear para variables de control.
Los parámetros se clasifican en dos: Parámetros por referencia, y parámetros por valor. Los de valor son los comunes de siempre, los que no tienen el "var". Se llaman "por valor" porque en realidad lo que hace el compilador es "copiar" el valor de la variable o constante del parámetro y trabajar dentro de la función con dicha copia. Una vez que la función termina, el valor de los parámetros queda como están: no cambian. Supongamos que  datoM sea "por valor", y que se pasa el valor 5... al finalizar la función seguiremos teniendo ese 5.

En cambio, los parámetros por referencia son aquellos en donde ves el "var". Lo que hace el compilador es trabajar con la variable exacta, por tanto se hace referencia a dicha zona de memoria. Si dentro de la función se cambia el valor de la variable, al finalizar no recuperaremos el valor original. Ahora en cambio, digamos que datoM es por referencia, al finalizar es posible que no sea 5, sino 8000 o vaya a saber uno.

Por ello he dicho que por lo general estos tipos de parámetros se emplean para "comunicar" que algo ha cambiado dentro de la función, son variables de "control". No se los suele usar como un dato de entrada. Puedes ver un ejemplo de uso de esta función en el evento OnCloseQuery, y en OnClose. Si te fijas, puedes cambiar el valor de CanClose y Action... dependiendo de como sea el valor final que obtengan, se hará una u otra cosa.

Saludos,

  • 0

#24 Fenareth

Fenareth

    Advanced Member

  • Administrador
  • 3.486 mensajes
  • LocationMexico City

Escrito 11 diciembre 2008 - 08:22

.....



delphi
  1. function Nombre(dato1, datoN: tipo; var datoM: tipo_M): tipo;
  2. ...



Ese parámetro datoM es tanto como de entrada como de salida. Se trata de un parámetro especial: nos permite que una función nos regrese otro valor más. Los procedimientos no regresan ningún valor, pero gracias a éste tipo de parámetro es posible devolver un valor.
Este parámetro por lo general es para "notificar" que algo ha cambiado dentro de la sentencia. Se lo suele emplear para variables de control.

Los parámetros se clasifican en dos: Parámetros por referencia, y parámetros por valor. Los de valor son los comunes de siempre, los que no tienen el "var". Se llaman "por valor" porque en realidad lo que hace el compilador es "copiar" el valor de la variable o constante del parámetro y trabajar dentro de la función con dicha copia. Una vez que la función termina, el valor de los parámetros queda como están: no cambian. Supongamos que  datoM sea "por valor", y que se pasa el valor 5... al finalizar la función seguiremos teniendo ese 5.

En cambio, los parámetros por referencia son aquellos en donde ves el "var". Lo que hace el compilador es trabajar con la variable exacta, por tanto se hace referencia a dicha zona de memoria. Si dentro de la función se cambia el valor de la variable, al finalizar no recuperaremos el valor original. Ahora en cambio, digamos que datoM es por referencia, al finalizar es posible que no sea 5, sino 8000 o vaya a saber uno.

Por ello he dicho que por lo general estos tipos de parámetros se emplean para "comunicar" que algo ha cambiado dentro de la función, son variables de "control". No se los suele usar como un dato de entrada. Puedes ver un ejemplo de uso de esta función en el evento OnCloseQuery, y en OnClose. Si te fijas, puedes cambiar el valor de CanClose y Action... dependiendo de como sea el valor final que obtengan, se hará una u otra cosa.

Saludos,


Algún mini ejemplo que lo ilustre mucho mejor ?  8-|
  • 0

#25 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 11 diciembre 2008 - 08:31

Hola amigo Delphius,

Los procedimientos no regresan ningún valor,



Perdón pero mas bien un procedimiento no puede asignarle un tipo de dato y a las funciones si se les asigna un tipo de dato. sin embargo los procedimientos si pueden tener variables que regresan un valor, pero se usan de manera distinta, veamos....



delphi
  1. procedure suma(dato1,dato2:integer; var dato3:integer);
  2. begin
  3.   dato3 := dato1+dato2;
  4. end;
  5.  
  6. procedure TForm1.Button1Click(Sender: TObject);
  7. var
  8.   uno,dos,tres: integer;
  9. begin
  10.   uno := 3;
  11.   dos := 5;
  12.   suma(uno,dos,tres);
  13.   showmessage(inttostr(tres));
  14. end;



Salud OS
  • 0

#26 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 11 diciembre 2008 - 08:43

Hola

Aqui las diferencias entre una función y un procedimiento.



delphi
  1. procedure suma(dato1,dato2:integer; var dato3:integer);
  2. begin
  3.   dato3 := dato1+dato2;
  4. end;
  5.  
  6. function resta(dato1,dato2:integer):integer;
  7. begin
  8.   result := dato2-dato1;
  9. end;
  10.  
  11. procedure TForm1.Button1Click(Sender: TObject);
  12. var
  13.   uno,dos,tres: integer;
  14. begin
  15.   uno := 3;
  16.   dos := 5;
  17.   suma(uno,dos,tres); //procedimiento
  18.   showmessage(inttostr(tres));
  19.   tres := resta(uno,dos); //función
  20.   showmessage(inttostr(tres));
  21. end;



Espero que sea mas claro aún el asunto :D

Salud OS
  • 0

#27 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 11 diciembre 2008 - 09:07

Veamos....
Deseamos Lanzar un cohete al espacio (cualquier similitud con algún hilo es pura concidencia :p :D), y una de las funciones que necesitamos es la de determinar si es posible lanzar el cohete.

Entonces un programador hace algo como esto:



delphi
  1. function PuedeLanzarCohete(NumeroCohete, Peso, Tamanno, CapacidadCombustible: integer): boolean;
  2. var CoheteValido: boolean;
  3. begin
  4.  CoheteValido := ValidarCohete(NumeroCohete); // Aquí se llama a una función!
  5.  if CoheteValido
  6.     then begin
  7.              result := (CapacidadCombustible <= (0.5 * Peso)) AND ((Peso/Tamanno) <= 1.5)
  8.              // Para poder lanzar el cohete, la capacidad del combustible debe ser cuanto mucho
  9.              // la mitad del peso y la proporción entre el Peso y el Tamaño no debe ser mayor a 1.5
  10.            end
  11.     result := False; // No se puede lanzar el cohete
  12. end;



Esta función les sirve, y el programador puede usarla sin problemas. Entonces cuando hace esto:



delphi
  1. var Puede: boolean; UnPeso, UnTamanno, UnaCapacidad: integer;
  2. ...
  3. UnPeso := 5000;
  4. unTamanno := 3400;
  5. UnaCapacidad := 2600;
  6. ...
  7. Puede := PuedeLanzarCohete(1,UnPeso,UnTamanno,UnaCapacidad);



Al finalizar la función, estas variables (UnPeso, UnTamanno, UnaCapacidad conservarán sus respectivos valores.

Pero supongamos que ahora, a los desarrolladores les gustaría saber porqué motivo no se puede lanzar. La función no puede regresar dos valores mediante "result". ¿La solución?: declarar un parámetro más anteponiendo el "var". Digamos que ahora queda así:



delphi
  1. function PuedeLanzarCohete(NumeroCohete, Peso, Tamanno, CapacidadCombustible: integer; var EstadoError: integer): boolean;
  2. var CoheteValido: boolean;
  3. begin
  4.  CoheteValido := ValidarCohete(NumeroCohete);
  5.  if CoheteValido
  6.     then begin
  7.               EstadoError := 0; // No hay error
  8.               result := True;
  9.               if (CapacidadCombustible > (0.5 * Peso)
  10.                  then begin
  11.                           EstadoError := EstadoError + 1;
  12.                           result := False;
  13.                         end;
  14.               if ((Peso/Tamanno) > 1.5)
  15.                  then begin
  16.                           EstadoError := EstadoError + 2;
  17.                           result := False;
  18.                         end;
  19.            end
  20.     else result := False;
  21. end;



Como puede verse, dentro de la función el parámetro EstadoError se lo trata como una variable más. Se ha diseñado esta variable para que asume cuatro resultados:
0 -> no hay error
1 -> se debe únicamente a un exceso en la capacidad de combustible
2 -> se debe únicamente a un exceso en el peso respecto al tamaño
3 -> se debe a las dos anteriores (1 + 2);

Ahora se declara una nueva variable global, le damos un valor (para pruebas) y ejecutamos la función:


delphi
  1. var Error: integer;
  2. ...
  3. Error := 5;
  4. Puede := PuedeLanzarCohete(1,UnPeso, UnTamanno, UnaCapacidad, Error);



Cuando finalize la rutina, todas las variables "UnXXX" no se modificarán, seguirán con los mismos valores (5000,3400,2600), pero "Error" se ve modificado puesto que se trata de un parámetro por referencia. Inicialmente le habíamos dado un valor 5, pero ahora si comprobamos su valor nos damos conque es 1.

De este modo podemos tomar una decisión y mejorar nuestro programa:



delphi
  1. Case Error of:
  2. 1: QuitarPesoCombustible(...);
  3. 2: QuitarPeso(...);
  4. 3: begin
  5.      ResidennarCohete(...)
  6.    end;
  7. else Lanzar(...);
  8. end;
  9. ...



Espero que con este mini ejemplo se entienda mejor.

Saludos,
PD: Las fórmulas son inventadas. No son representaciones de la realidad... para estar seguros consultar a la NASA :D
  • 0

#28 Fenareth

Fenareth

    Advanced Member

  • Administrador
  • 3.486 mensajes
  • LocationMexico City

Escrito 11 diciembre 2008 - 11:25

Amiguito Delphius, me queda PERFECTAMENTE claro  :D

Te agradezco muchisimo tu tiempo para explicarlo, sinceramente disfruto aprendiendo mucho de tus hilos  :) :)
  • 0

#29 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 12 diciembre 2008 - 06:37

Amiguito Delphius, me queda PERFECTAMENTE claro  :D

Te agradezco muchisimo tu tiempo para explicarlo, sinceramente disfruto aprendiendo mucho de tus hilos  :) :)


Muchas gracias,
Disfruté mucho escribiendo el post y quise ser breve pero demostrativo de los conceptos.
Lo que si sería bueno es analizar si realmente no confundí "parámetros por referencia" con "parámetros por valor". La diferencia en un sentido práctico la manejo, lo que no estoy totalmente seguro es si los nombres son los correctos. Tiendo a confundirlos (¡Y esto es algo básico en programación :|!). ¿Los var son los llamados por referencia? ¿O es alrrevez? :s

Saludos,
  • 0

#30 eduarcol

eduarcol

    Advanced Member

  • Administrador
  • 4.483 mensajes
  • LocationVenezuela

Escrito 12 diciembre 2008 - 07:27

ok, esa si me la se...


Los parametros por referencia son los var, y se llaman asi debido a que la funcion lo que recibe es la referencia de memoria (puntero) donde reside la variable, por eso se puede modificar.  Los parametros por valor reciben es el contenido de la direccion de memoria y lo carga en otro bloque.

Ahora quien se lanza con una de recursividad?? jejeje
  • 0

#31 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 12 diciembre 2008 - 08:49

ok, esa si me la se...


Los parametros por referencia son los var, y se llaman asi debido a que la funcion lo que recibe es la referencia de memoria (puntero) donde reside la variable, por eso se puede modificar.  Los parametros por valor reciben es el contenido de la direccion de memoria y lo carga en otro bloque.

Ahora quien se lanza con una de recursividad?? jejeje

Muchas gracias Eduardo,
Normalmente dudo de eso... no se porqué tiendo a confundirlos.
¡Por Dios! ¡Pero si es algo elemental y fundamental!
Que lo tiró... parece que el sector de mi cerebro donde se encontraba este dato está defectuoso. ¡ScanDisk! :p :|

Saludos,
  • 0

#32 eduarcol

eduarcol

    Advanced Member

  • Administrador
  • 4.483 mensajes
  • LocationVenezuela

Escrito 12 diciembre 2008 - 09:02

entonces Carlitos, le entras a una de funciones recursivas?? estas dispuesto a volverte loco jejeje ;), imagina una funcion que se llame a ella misma, interesante verdad :p
  • 0

#33 seoane

seoane

    Advanced Member

  • Administrador
  • 1.259 mensajes
  • LocationEspaña

Escrito 12 diciembre 2008 - 10:00

Yo me atrevo con la recursividad  :p

Pues la recursividad no es mas que una funcion que se llama a si misma.

Por ejemplo la funcion factorial*:


delphi
  1. function factorial(x: Integer): Integer;
  2. begin
  3.   if x = 1 then
  4.     Result:= 1
  5.   else
  6.     Result:= x * factorial(x-1);
  7. end;


*Para todo número natural n, se llama n factorial o factorial de n al producto de todos los naturales desde 1 hasta n:
*Aunque el factorial de 0 es 1 en la función anterior no lo pongo por simplicidad

En la función anterior se pueden ver las dos características principales de una función recursiva:
- Se llama a si misma
- Existe una condición (que se debe de cumplir siempre) que termina el proceso.

No siempre es fácil ni aconsejable usar la recursividad, pero hay problemas cuya solución parece ideal para usar recursividad, como por ejemplo el factorial, búsqueda de ficheros en subdirectorios, etc ...
  • 0

#34 eduarcol

eduarcol

    Advanced Member

  • Administrador
  • 4.483 mensajes
  • LocationVenezuela

Escrito 12 diciembre 2008 - 10:07

Es importante el punto que mencionas de la condicion que rompe el ciclo, de no haberla se provoca un desbordamiento de pila.


PD: No, no es la pila(batería) del  Bios  :D
  • 0

#35 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 12 diciembre 2008 - 11:22

Yo me juego con otra sencillita: la serie de Fibonachi.


delphi
  1. function Fibonachi(N: integer): integer;
  2. begin
  3.   if N < 2
  4.     then result := N
  5.     else result := Fibonachi(N - 1) + Fibonachi(N - 2);
  6. end;



No lo corrí, pero si está todo bien debería andar ;). Ya no recuerdo estos ejercicios bien del todo. :p

Saludos,
  • 0

#36 FGarcia

FGarcia

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 687 mensajes
  • LocationMéxico

Escrito 14 diciembre 2008 - 11:04

Y con esto de las funciones ¿como retornar diferentes valores en una funcion?
Es decir por ejemplo una funcion que recibe dos parametros y debe retornar 3 valores diferentes



delphi
  1. function MiFuncion(Param1,Param2:alguntipo):integer,double,tdatetime;
  2. begin
  3.   //Lo que tenga que hacer
  4. end;


  • 0

#37 eduarcol

eduarcol

    Advanced Member

  • Administrador
  • 4.483 mensajes
  • LocationVenezuela

Escrito 15 diciembre 2008 - 07:28

Hasta donde llegan mis conocimientos eso no se puede, para poder retornar mas de un valor puedes utilizar los parametros por referencia
  • 0

#38 seoane

seoane

    Advanced Member

  • Administrador
  • 1.259 mensajes
  • LocationEspaña

Escrito 15 diciembre 2008 - 07:54

Hasta donde llegan mis conocimientos eso no se puede, para poder retornar mas de un valor puedes utilizar los parametros por referencia

O tambien se puede declarar un tipo record y usarlo como resultado de la funcion.

Me explico  :D


delphi
  1. type
  2.   TResultado = record
  3.       Entero: Integer;
  4.       Doble: double,
  5.       Fecha: TDatetime;
  6.   end;
  7.  
  8. function MiFuncion(Param1,Param2:alguntipo): TResultado;
  9. begin
  10.   //Lo que tenga que hacer
  11. end;
  12.  
  13.  
  14. // Y usarioamos la funcion asi:
  15. var
  16.   Resultado: TResultado;
  17. begin
  18.   Resultado:= MiFuncion(P1,P2);
  19.   ShowMessage('El entero es: ' + IntToStr(Resultado.Entero));
  20.   ShowMessage('La fecha es: ' + DateToStr(Resultado.Fecha));
  21. end;


  • 0

#39 eduarcol

eduarcol

    Advanced Member

  • Administrador
  • 4.483 mensajes
  • LocationVenezuela

Escrito 15 diciembre 2008 - 08:28

Excelente Seoane
  • 0

#40 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 15 diciembre 2008 - 09:37

Chanclas, que interesante ese asunto de regresar mas de un tipo de valor en una función (y), cada día se aprende algo nuevo.

Solo complementando lo publicado por seoane, pues tenia la duda de como era que se debian regresar los valores me puse a hacer varias alternativas y era mas facil de lo que pense :s.



delphi
  1. function MiFuncion(Param1,Param2:integer): TResultado;
  2. begin
  3.   Result.Entero := 102;
  4.   Result.Doble  := 12345;
  5.   Result.Fecha  := Now;
  6. end;
  7.  
  8. procedure TForm1.Button1Click(Sender: TObject);
  9. var
  10.   Resultado: TResultado;
  11. begin
  12.   Resultado := MiFuncion(122,132);
  13.   ShowMessage('El entero es: ' + IntToStr(Resultado.Entero));
  14.   ShowMessage('El doble es: ' + IntToStr(Resultado.Doble));
  15.   ShowMessage('La fecha es: ' + DateToStr(Resultado.Fecha));
  16. end;



Salud OS
  • 0




IP.Board spam blocked by CleanTalk.