{"id":277,"date":"2023-03-20T10:51:09","date_gmt":"2023-03-20T10:51:09","guid":{"rendered":"https:\/\/jorgeturiel.es\/?p=277"},"modified":"2023-04-03T10:49:21","modified_gmt":"2023-04-03T09:49:21","slug":"introduccion-al-lenguaje-pascal-moderno-para-programadores-parte-1","status":"publish","type":"post","link":"https:\/\/jorgeturiel.es\/?p=277","title":{"rendered":"Introducci\u00f3n al lenguaje Pascal moderno para programadores (Parte 1)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Mucha gente considera el lenguaje Pascal, como un lenguaje obsoleto, ya que en internet hay muchos recurso que hablan sobre el lenguaje Pascal, pero hablan sobre el \u00abviejo\u00bb Pascal.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Michalis Kamburelis, creador del motor gr\u00e1fico <a rel=\"noreferrer noopener\" href=\"https:\/\/castle-engine.io\" target=\"_blank\">Castle Engine<\/a>, escribi\u00f3 una gu\u00eda muy concisa y sencilla, en la que muestra las caracter\u00edsticas  de este lenguaje.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En esta entrada y sucesivas encontrar\u00e1s la traducci\u00f3n al espa\u00f1ol de este texto.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">El texto original se puede encontrar <a rel=\"noreferrer noopener\" href=\"https:\/\/castle-engine.io\/modern_pascal\" target=\"_blank\">aqu\u00ed<\/a>.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">\u00bfPor qu\u00e9?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Hay muchos libros y recursos sobre Pascal, pero muchos de ellos hablan sobre el antiguo Pascal, sin clases, unidades o gen\u00e9ricos.\n\nAs\u00ed que escrib\u00ed esta r\u00e1pida introducci\u00f3n a lo que llamo Object Pascal moderno. La mayor\u00eda de los programadores que lo usan realmente no lo llaman \u00abObjeto Pascal moderno\u00bb, simplemente lo llamamos \u00abnuestro Pascal\u00bb. Pero al presentar el lenguaje, creo que es importante enfatizar que es un lenguaje moderno y orientado a objetos. Evolucion\u00f3 mucho desde el viejo (Turbo) Pascal que mucha gente aprendi\u00f3 en las escuelas hace mucho tiempo. En cuanto a las funciones, es bastante similar a C++, Java o C#.\n\n    Tiene todas las caracter\u00edsticas modernas que espera: clases, unidades, interfaces, gen\u00e9ricos&#8230;\n\n    Est\u00e1 compilado en un c\u00f3digo nativo r\u00e1pido,\n\n    Es muy tipo seguro,\n\n    De alto nivel, pero tambi\u00e9n puede ser de bajo nivel si lo necesita.\n\nTambi\u00e9n tiene un compilador excelente, port\u00e1til y de c\u00f3digo abierto llamado Free Pascal Compiler, http:\/\/freepascal.org\/. Y un IDE que lo acompa\u00f1a (editor, depurador, una biblioteca de componentes visuales, dise\u00f1ador de formularios) llamado Lazarus http:\/\/lazarus.freepascal.org\/. Yo mismo, soy el creador de Castle Game Engine, https:\/\/castle-engine.io\/, que es un motor de juegos 3D y 2D de c\u00f3digo abierto que utiliza Pascal moderno para crear juegos en muchas plataformas (Windows, Linux, macOS, Android, iOS, Nintendo Switch; tambi\u00e9n viene WebGL).\n\nEsta introducci\u00f3n est\u00e1 dirigida principalmente a programadores que ya tienen experiencia en otros lenguajes. No cubriremos aqu\u00ed los significados de algunos conceptos universales, como \u00abqu\u00e9 es una clase\u00bb, solo mostraremos c\u00f3mo hacerlo en Pascal.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"> B\u00e1sico<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Hola Mundo<\/h3>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">{$mode objfpc}{$H+}{$J-} \/\/ Usa esta l\u00ednea en todos los recursos\n\nprogram MyProgram; \/\/ guarda este programa como myprogram.lpr\nbegin\n  WriteLn('Hola Mundo!');\nend.<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Este es un programa completo que puede compilar y ejecutar.          Este es un programa de l\u00ednea de comandos, por lo que en cualquier caso\u2009\u2014\u2009simplemente ejecute el ejecutable compilado desde la l\u00ednea de comandos.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Si usa la l\u00ednea de comandos FPC, simplemente cree un nuevo archivo <em>myprogram.lpr<\/em> y ejecute <em>fpc myprogram.lpr<\/em><\/li>\n\n\n\n<li>Si usas Lazarus, cree un nuevo proyecto (men\u00fa Proyecto \u2192 Nuevo proyecto \u2192 Programa Simple). Gu\u00e1rdelo como myprogram y pegue este c\u00f3digo fuente como archivo principal. Compilar utilizando el elemento de men\u00fa Ejecutar \u2192 Compilar.<\/li>\n\n\n\n<li>Este es un programa de l\u00ednea de comandos, por lo que en cualquier caso,\u2009simplemente ejecute el ejecutable compilado desde la l\u00ednea de comandos. <\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">El resto de este art\u00edculo habla sobre el lenguaje Object Pascal, as\u00ed que no esperes ver nada m\u00e1s elegante que la l\u00ednea de comandos. Si quiere ver algo genial, simplemente cree un nuevo proyecto GUI en Lazarus (Proyecto \u2192 Nuevo proyecto \u2192 Aplicaci\u00f3n). Listo\u2009\u2014\u2009una aplicaci\u00f3n GUI en funcionamiento, multiplataforma, con un aspecto nativo en todas partes, que utiliza una c\u00f3moda biblioteca de componentes visuales. El compilador Lazarus y Free Pascal vienen con muchas unidades listas para redes, GUI, base de datos, formatos de archivo (XML, json, im\u00e1genes&#8230;), subprocesos y todo lo que pueda necesitar. Ya mencion\u00e9 mi genial <a rel=\"noreferrer noopener\" href=\"http:\/\/castle-engine.io\/\" target=\"_blank\">Castle Game Engine<\/a> antes \ud83d\ude42<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Funciones procedimientos y tipos primitivos<\/h3>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">{$mode objfpc}{$H+}{$J-}\n\nprogram MyProgram;\n\nprocedure MyProcedure(const A: Integer);\nbegin\n  WriteLn('A + 10 is: ', A + 10);\nend;\n\nfunction MyFunction(const S: string): string;\nbegin\n  Result := S + 'strings are automatically managed';\nend;\n\nvar\n  X: Single;\nbegin\n  WriteLn(MyFunction('Note: '));\n  MyProcedure(5);\n\n  \/\/ Division using \"\/\" always makes float result, use \"div\" for integer division\n  X := 15 \/ 5;\n  WriteLn('X is now: ', X); \/\/ scientific notation\n  WriteLn('X is now: ', X:1:2); \/\/ 2 decimal places\nend.<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Para devolver un valor de una funci\u00f3n, asigne algo a la variable de m\u00e1gica <em>Result<\/em>. Puede leer y configurar <em>Result<\/em> libremente, como una variable local.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">function MyFunction(const S: string): string;\nbegin\n  Result := S + 'something';\n  Result := Result + ' something more!';\n  Result := Result + ' and more!';\nend;<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Tambi\u00e9n puede tratar el nombre de la funci\u00f3n (como MyFunction en el ejemplo anterior) como la variable a la que puede asignar datos. Pero lo desaconsejar\u00eda en el c\u00f3digo nuevo, ya que parece \u00absospechoso\u00bb cuando se usa en el lado derecho de la expresi\u00f3n de asignaci\u00f3n. Simplemente use Result siempre cuando quiera leer o configurar el resultado de la funci\u00f3n.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">function SumIntegersUntilZero: Integer;\nvar\n  I: Integer;\nbegin\n  Readln(I);\n  Result := I;\n  if I &lt;&gt; 0 then\n    Result := Result + SumIntegersUntilZero();\nend;<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-rmn\">Puede llamar a Exit para finalizar la ejecuci\u00f3n del procedimiento o funci\u00f3n antes de que llegue al final final;. Si llama a Exit sin par\u00e1metros en una funci\u00f3n, devolver\u00e1 lo \u00faltimo que configur\u00f3 como Result. Tambi\u00e9n puede usar la construcci\u00f3n Exit(X), para establecer el resultado de la funci\u00f3n y salir ahora\u2009\u2014\u2009esto es como devolver la construcci\u00f3n X en lenguajes similares a C.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">function AddName(const ExistingNames, NewName: string): string;\nbegin\n  if ExistingNames = '' then\n    Exit(NewName);\n  Result := ExistingNames + ', ' + NewName;\nend;<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Tenga en cuenta que el resultado de la funci\u00f3n se puede descartar. Cualquier funci\u00f3n puede usarse como un procedimiento. Esto tiene sentido si la funci\u00f3n tiene alg\u00fan efecto secundario (por ejemplo, modifica una variable global) adem\u00e1s de calcular el resultado. Por ejemplo:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">var\n  Count: Integer;\n  MyCount: Integer;\n\nfunction CountMe: Integer;\nbegin\n  Inc(Count);\n  Result := Count;\nend;\n\nbegin\n  Count := 10;\n  CountMe; \/\/ the function result is discarded, but the function is executed, Count is now 11\n  MyCount := CountMe; \/\/ use the result of the function, MyCount equals to Count which is now 12\nend.<\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Testing (if)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Use if .. then o if .. then .. else para ejecutar alg\u00fan c\u00f3digo cuando se cumpla alguna condici\u00f3n. A diferencia de los lenguajes tipo C, en Pascal no tienes que envolver la condici\u00f3n entre par\u00e9ntesis.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">var\n  A: Integer;\n  B: boolean;\nbegin\n  if A &gt; 0 then\n    DoSomething;\n\n  if A &gt; 0 then\n  begin\n    DoSomething;\n    AndDoSomethingMore;\n  end;\n\n  if A &gt; 10 then\n    DoSomething\n  else\n    DoSomethingElse;\n\n  \/\/ equivalent to above\n  B := A &gt; 10;\n  if B then\n    DoSomething\n  else\n    DoSomethingElse;\nend;<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">El else est\u00e1 emparejado con el \u00faltimo if. Entonces esto funciona como esperas:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">if A &lt;&gt; 0 then\n  if B &lt;&gt; 0 then\n    AIsNonzeroAndBToo\n  else\n    AIsNonzeroButBIsZero;<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Si bien el ejemplo con el si anidado anterior es correcto, a menudo es mejor colocar el si anidado dentro de un bloque de inicio \u2026 final en tales casos. Esto hace que el c\u00f3digo sea m\u00e1s obvio para el lector y seguir\u00e1 siendo obvio incluso si estropeas la sangr\u00eda. La versi\u00f3n mejorada del ejemplo se encuentra a continuaci\u00f3n. Cuando agrega o elimina alguna otra cl\u00e1usula en el c\u00f3digo a continuaci\u00f3n, es obvio a qu\u00e9 condici\u00f3n se aplicar\u00e1 (a la prueba A o la prueba B), por lo que es menos propenso a errores.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">if A &lt;&gt; 0 then\nbegin\n  if B &lt;&gt; 0 then\n    AIsNonzeroAndBToo\n  else\n    AIsNonzeroButBIsZero;\nend;<\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Operadores l\u00f3gicos, relacionales y bit a bit<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Los operadores l\u00f3gicos se llaman and, or, not, xor. Su significado es probablemente obvio (busque \u00abexclusivo o\u00bb si no est\u00e1 seguro de lo que hace xor :)). Toman argumentos booleanos y devuelven un booleano. Tambi\u00e9n pueden actuar como operadores bit a bit cuando ambos argumentos son valores enteros, en cuyo caso devuelven un n\u00famero entero.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-rmn\">Los operadores relacionales (de comparaci\u00f3n) son =, &lt;&gt;, &gt;, &lt;, &lt;=, &gt;=. Si est\u00e1 acostumbrado a lenguajes similares a C, tenga en cuenta que en Pascal compara dos valores (verifique si son iguales) usando un solo car\u00e1cter de igualdad A = B (a diferencia de C donde usa A == B). El operador de asignaci\u00f3n especial en Pascal es :=.\n\n<\/p>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Los operadores l\u00f3gicos (o bit a bit) tienen mayor precedencia que los operadores relacionales. Es posible que deba usar par\u00e9ntesis alrededor de algunas expresiones para tener el orden deseado de los c\u00e1lculos.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Por ejemplo, esto es un error de compilaci\u00f3n:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">var\n  A, B: Integer;\nbegin\n  if A = 0 and B &lt;&gt; 0 then ... \/\/ INCORRECT example\n\n<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Lo anterior falla al compilar, porque el compilador primero quiere realizar un bit a bit y en el medio de la expresi\u00f3n: (0 y B). Esta es una operaci\u00f3n bit a bit que devuelve un valor entero. Luego, el compilador aplica el operador = que produce un valor booleano A = (0 y B). Y finalmente, el error de \u00abtipo no coincidente\u00bb surge despu\u00e9s de intentar comparar el valor booleano A = (0 y B) y el valor entero 0.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Esto es correcto:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">var\n  A, B: Integer;\nbegin\n  if (A = 0) and (B &lt;&gt; 0) then ...<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Se utiliza la evaluaci\u00f3n de \u00abcortocircuito\u00bb. Considere esta expresi\u00f3n:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">if MyFunction(X) and MyOtherFunction(Y) then...<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li><\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li> Est\u00e1 garantizado que <em>MyFuncion(X) se evaluar\u00e1 primero.<\/em><\/li>\n\n\n\n<li>Y si <em>MyFunction(x)<\/em> devuelve falso, entonces la valor de la expresi\u00f3n ser\u00e1 falso, y <em>MyOtherFunction(Y)<\/em> no se ejecutar\u00e1 en absoluto.<\/li>\n\n\n\n<li>De manera an\u00e1loga es para el operador OR. Si se sabe que la expresi\u00f3n es verdadera (porque el primer operador es verdadero), el segundo operador no se evaluar\u00e1.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Esto es particularmente \u00fatil cuando se escriben expresiones como:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">if (A &lt;&gt; nil) and A.IsValid then...<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-rmn\">\nLa regla an\u00e1loga es para o expresi\u00f3n. All\u00ed, si se sabe que la expresi\u00f3n es verdadera (porque el primer operando es verdadero), el segundo operando no se eval\u00faa.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Esto funcionar\u00e1 bien, incluso cuando A es nulo. La palabra clave <em>nil<\/em> es un puntero igual a cero (cuando se representa como un n\u00famero). Se llama puntero nulo en muchos otros lenguajes de programaci\u00f3n.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Prueba de expresi\u00f3n \u00fanica para valores m\u00faltiples (case)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Si se debe ejecutar una acci\u00f3n diferente dependiendo del valor de alguna expresi\u00f3n, entonces la instrucci\u00f3n case .. of .. end es \u00fatil.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">case SomeValue of\n  0: DoSomething;\n  1: DoSomethingElse;\n  2: begin\n       IfItsTwoThenDoThis;\n       AndAlsoDoThis;\n     end;\n  3..10: DoSomethingInCaseItsInThisRange;\n  11, 21, 31: AndDoSomethingForTheseSpecialValues;\n  else DoSomethingInCaseOfUnexpectedValue;\nend;<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">La cl\u00e1usula else es opcional (y corresponde a la predeterminada en lenguajes tipo C). Cuando ninguna condici\u00f3n coincide, y no hay m\u00e1s, entonces no pasa nada.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Si proviene de lenguajes similares a C y compara esto con la declaraci\u00f3n de cambio en estos lenguajes, notar\u00e1 que no hay fallas autom\u00e1ticas. Esta es una bendici\u00f3n deliberada en Pascal. No es necesario que recuerde colocar las instrucciones de descanso. En cada ejecuci\u00f3n, como m\u00e1ximo se ejecuta una rama del caso, eso es todo.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Tipos y conjuntos enumerados, ordinales y matrices de longitud constante<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">El tipo enumerado en Pascal es un tipo muy agradable y opaco. Probablemente lo usar\u00e1 con mucha m\u00e1s frecuencia que las enumeraciones en otros idiomas \ud83d\ude42<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">type\n  TAnimalKind = (akDuck, akCat, akDog);<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">La convenci\u00f3n es prefijar los nombres de enumeraci\u00f3n con un atajo de dos letras de nombre de tipo, por lo tanto, ak = atajo para \u00abAnimal Kind\u00bb. Esta es una convenci\u00f3n \u00fatil, ya que los nombres de enumeraci\u00f3n est\u00e1n en el espacio de nombres de la unidad (global). Entonces, al anteponerles el prefijo ak, minimiza las posibilidades de colisiones con otros identificadores.\n\n<\/p>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Las coincidencias en los nombres no son un problema. Es correcto que diferentes unidades definan el mismo identificador. Pero es una buena idea tratar de evitar las coincidencias de todos modos, para mantener el c\u00f3digo simple de entender.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Puede evitar colocar nombres de enumeraci\u00f3n en el espacio de nombres global mediante la directiva del compilador <em>{$scopedenums on}<\/em>. Esto significa que tendr\u00e1 que acceder a ellos calificados por un nombre de tipo, como <em>TAnimalKind.akDuck<\/em>. La necesidad del prefijo ak desaparece en esta situaci\u00f3n, y probablemente llamar\u00e1s a las enumeraciones Pato, Gato, Perro. Esto es similar a las enumeraciones de C#.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">El hecho de que el tipo enumerado sea opaco significa que no se puede asignar simplemente a un n\u00famero entero. Sin embargo, para un uso especial, puede usar <em>Ord(MyAnimalKind)<\/em> para convertir forzosamente <em>enum<\/em> a <em>int<\/em>, o <em>typecast<\/em> <em>TAnimalKind(MyInteger) <\/em>para convertir forzosamente <em>int<\/em> en <em>enum<\/em>. En el \u00faltimo caso, aseg\u00farese de comprobar primero si <em>MyInteger<\/em> est\u00e1 dentro del rango (0 a <em>Ord(High(TAnimalKind)<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Los tipos enumerados y ordinales se pueden usar como \u00edndices de matriz:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">type\n  TArrayOfTenStrings = array [0..9] of string;\n  TArrayOfTenStrings1Based = array [1..10] of string;\n\n  TMyNumber = 0..9;\n  TAlsoArrayOfTenStrings = array [TMyNumber] of string;\n\n  TAnimalKind = (akDuck, akCat, akDog);\n  TAnimalNames = array [TAnimalKind] of string;<\/pre><\/div>\n\n\n\n<pre id=\"tw-target-text\" class=\"wp-block-preformatted\">Tambi\u00e9n se pueden usar para crear conjuntos (un campo de bits internamente):<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-rmn\">Tambi\u00e9n se pueden usar para crear conjuntos (un campo de bits internamente):\n\n<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">type\n  TAnimalKind = (akDuck, akCat, akDog);\n  TAnimals = set of TAnimalKind;\nvar\n  A: TAnimals;\nbegin\n  A := [];\n  A := [akDuck, akCat];\n  A := A + [akDog];\n  A := A * [akCat, akDog];\n  Include(A, akDuck);\n  Exclude(A, akDuck);\nend;<\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Bucles (for, while, repeat, for .. in)<\/h3>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">{$mode objfpc}{$H+}{$J-}\n{$R+} \/\/ range checking on - nice for debugging\nvar\n  MyArray: array [0..9] of Integer;\n  I: Integer;\nbegin\n  \/\/ initialize\n  for I := 0 to 9 do\n    MyArray[I] := I * I;\n\n  \/\/ show\n  for I := 0 to 9 do\n    WriteLn('Square is ', MyArray[I]);\n\n  \/\/ does the same as above\n  for I := Low(MyArray) to High(MyArray) do\n    WriteLn('Square is ', MyArray[I]);\n\n  \/\/ does the same as above\n  I := 0;\n  while I &lt; 10 do\n  begin\n    WriteLn('Square is ', MyArray[I]);\n    I := I + 1; \/\/ or \"I += 1\", or \"Inc(I)\"\n  end;\n\n  \/\/ does the same as above\n  I := 0;\n  repeat\n    WriteLn('Square is ', MyArray[I]);\n    Inc(I);\n  until I = 10;\n\n  \/\/ does the same as above\n  \/\/ note: here I enumerates MyArray values, not indexes\n  for I in MyArray do\n    WriteLn('Square is ', I);\nend.<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Sobre  <code>los bucles repeat<\/code> y <code>while<\/code><\/strong>:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Hay dos diferencias entre estos tipos de bucle: <\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>La condici\u00f3n de bucle tiene un significado opuesto. En mientras.. le dices cuando continuar, pero en repetir.. hasta que le dices cuando parar.<\/li>\n\n\n\n<li>En caso de repetici\u00f3n, la condici\u00f3n no se comprueba al principio. Entonces, el ciclo de repetici\u00f3n siempre se ejecuta al menos una vez.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\"><strong>Sobre el bucle <code>for I := \u2026\u200b<\/code><\/strong>:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">El for I := .. to .. do \u2026\u200b lo construye de manera similar al bucle for tipo C. Sin embargo, est\u00e1 m\u00e1s restringido, ya que no puede especificar acciones\/pruebas arbitrarias para controlar la iteraci\u00f3n del bucle. Esto es estrictamente para iterar sobre n\u00fameros consecutivos (u otros tipos ordinales). La \u00fanica flexibilidad que tiene es que puede usar downto en lugar de to para hacer que los n\u00fameros vayan hacia abajo.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A cambio, se ve limpio y est\u00e1 muy optimizado en ejecuci\u00f3n. En particular, las expresiones para el l\u00edmite inferior y superior solo se calculan una vez, antes de que comience el bucle.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Tenga en cuenta que el valor de la variable del contador del ciclo (I en este ejemplo) debe considerarse indefinido despu\u00e9s de que finalice el ciclo, debido a posibles optimizaciones. Acceder al valor de I despu\u00e9s del bucle puede provocar una advertencia del compilador. A menos que salga del ciclo prematuramente con Break o Exit: en tal caso, se garantiza que la variable contador conservar\u00e1 el \u00faltimo valor.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Sobre el buvle  <code>for I in \u2026\u200b<\/code> <\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">El for I en .. do .. es similar a la construcci\u00f3n foreach en muchos lenguajes modernos. Funciona de forma inteligente en muchos tipos integrados:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Puede iterar sobre todos los valores de la matriz (ejemplo anterior).<\/li>\n\n\n\n<li>Puede iterar sobre todos los valores posibles de un tipo enumerado: <\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">var\n  AK: TAnimalKind;\nbegin\n  for AK in TAnimalKind do...<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Puede iterar sobre todos los elementos incluidos en el conjunto:<\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">var\n  Animals: TAnimals;\n  AK: TAnimalKind;\nbegin\n  Animals := [akDog, akCat];\n  for AK in Animals do ...<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Y funciona en tipos de listas personalizadas, gen\u00e9ricas o no, como TObjectList o TFPGObjectList.<\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">{$mode objfpc}{$H+}{$J-}\nuses\n  SysUtils, FGL;\n\ntype\n  TMyClass = class\n    I, Square: Integer;\n  end;\n  TMyClassList = specialize TFPGObjectList&lt;TMyClass&gt;;\n\nvar\n  List: TMyClassList;\n  C: TMyClass;\n  I: Integer;\nbegin\n  List := TMyClassList.Create(true); \/\/ true = owns children\n  try\n    for I := 0 to 9 do\n    begin\n      C := TMyClass.Create;\n      C.I := I;\n      C.Square := I * I;\n      List.Add(C);\n    end;\n\n    for C in List do\n      WriteLn('Square of ', C.I, ' is ', C.Square);\n  finally\n    FreeAndNil(List);\n  end;\nend.<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Todav\u00eda no explicamos el concepto de clases, por lo que el \u00faltimo ejemplo puede no ser obvio para usted todav\u00eda\u2009\u2014\u2009solo contin\u00fae, tendr\u00e1 sentido m\u00e1s adelante \ud83d\ude42 <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Salida, Logging<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Para simplemente generar cadenas en Pascal, use la rutina Write o WriteLn. Este \u00faltimo agrega autom\u00e1ticamente una nueva l\u00ednea al final.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Esta es una rutina \u00abm\u00e1gica\u00bb en Pascal. Toma un n\u00famero variable de argumentos y pueden ser de cualquier tipo. Todos se convierten en cadenas cuando se muestran, con una sintaxis especial para especificar el relleno y la precisi\u00f3n num\u00e9rica.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">WriteLn('Hello world!');\nWriteLn('You can output an integer: ', 3 * 4);\nWriteLn('You can pad an integer: ', 666:10);\nWriteLn('You can output a float: ', Pi:1:4);<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Para usar expl\u00edcitamente una nueva l\u00ednea en la cadena, use la constante LineEnding (de FPC RTL). (El Castle Game Engine define tambi\u00e9n una constante NL m\u00e1s corta.) Las cadenas de Pascal no interpretan ninguna secuencia especial de barra invertida, por lo que escribir<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">WriteLn('One line.\\nSecond line.'); \/\/ INCORRECT example<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">no funciona como algunos de ustedes pensar\u00edan. Esto funcionar\u00e1:\u00e7<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">WriteLn('One line.' + LineEnding + 'Second line.');<\/pre><\/div>\n\n\n\n<pre id=\"tw-source-rmn\" class=\"wp-block-preformatted\"><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">o solo esto:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">WriteLn('One line.');\nWriteLn('Second line.');<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">\/<\/p>\n\n\n\n<pre id=\"tw-source-rmn\" class=\"wp-block-preformatted\"><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Tenga en cuenta que esto solo funcionar\u00e1 en aplicaciones de consola. Aseg\u00farese de tener {$apptype CONSOLE} (y no {$apptype GUI}) definido en su archivo de programa principal. En algunos sistemas operativos en realidad no importa y funcionar\u00e1 siempre (Unix), pero en algunos sistemas operativos intentar escribir algo desde una aplicaci\u00f3n GUI es un error (Windows).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">En Castle Game Engine: use WriteLnLog o WriteLnWarning, nunca WriteLn, para imprimir informaci\u00f3n de depuraci\u00f3n. Siempre se dirigir\u00e1n a alguna salida \u00fatil. En Unix, salida est\u00e1ndar. En la aplicaci\u00f3n de GUI de Windows, archivo de registro. En Android, la funci\u00f3n de registro de Android (visible cuando usa adb logcat). El uso de WriteLn debe limitarse a los casos en los que escribe una aplicaci\u00f3n de l\u00ednea de comandos (como un convertidor\/generador de modelos 3D) y sabe que la salida est\u00e1ndar est\u00e1 disponible.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Convirtiendo a cadena<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Para convertir un n\u00famero arbitrario de argumentos en una cadena (en lugar de generarlos directamente), tiene un par de opciones.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">Puede convertir tipos particulares en cadenas usando funciones especializadas como <em>IntToStr<\/em> y <em>FloatToStr<\/em>. Adem\u00e1s, puedes concatenar cadenas en Pascal simplemente agreg\u00e1ndolas. Entonces puedes crear una cadena como esta:<em> Mi n\u00famero int es &#8216; + IntToStr(MyInt) + &#8216;, y el valor de Pi es &#8216; + FloatToStr(Pi).<\/em><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ventaja: Absolutamente flexible. Hay muchas versiones sobrecargadas de XxxToStr y amigos (como FormatFloat), que cubren muchos tipos. La mayor\u00eda de ellos est\u00e1n en la unidad SysUtils.<\/li>\n\n\n\n<li>Otra ventaja: Consistente con las funciones inversas. Para convertir una cadena (por ejemplo, la entrada del usuario) de nuevo en un n\u00famero entero o flotante, use StrToInt, StrToFloat y amigos (como StrToIntDef).<\/li>\n\n\n\n<li>Desventaja: una concatenaci\u00f3n larga de muchas llamadas y cadenas XxxToStr no se ve bien.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\">  La funci\u00f3n Format, utilizada como<em> Format(&#8216;%d %f %s&#8217;, [MyInt, MyFloat, MyString])<\/em>. Esto es como la funci\u00f3n sprintf en los lenguajes tipo C. Inserta los argumentos en los marcadores de posici\u00f3n en el patr\u00f3n. Los marcadores de posici\u00f3n pueden usar una sintaxis especial para influir en el formato, p. %.4f da como resultado un formato de punto flotante con 4 d\u00edgitos despu\u00e9s del punto decimal.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ventaja: la separaci\u00f3n de la cadena de patr\u00f3n de los argumentos parece limpia. Si necesita cambiar la cadena del patr\u00f3n sin tocar los argumentos (por ejemplo, al traducir), puede hacerlo f\u00e1cilmente.<\/li>\n\n\n\n<li>Otra ventaja: no hay magia de compilaci\u00f3n. Puede usar la misma sintaxis para pasar cualquier cantidad de argumentos de un tipo arbitrario en sus propias rutinas (declare el par\u00e1metro como una matriz de const). Luego puede pasar estos argumentos hacia abajo a Formato, o deconstruir la lista de par\u00e1metros y hacer lo que quiera con ellos.<\/li>\n\n\n\n<li>Desventaja: el compilador no verifica si el patr\u00f3n coincide con los argumentos. El uso de un tipo de marcador de posici\u00f3n incorrecto dar\u00e1 como resultado una excepci\u00f3n en tiempo de ejecuci\u00f3n (excepci\u00f3n EConvertError, nada desagradable como un error de segmentaci\u00f3n).<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\" id=\"tw-target-text\"> La rutina WriteStr(TargetString, \u2026\u200b) se comporta de manera similar a Write(\u2026\u200b), excepto que el resultado se guarda en TargetString. <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ventaja: admite todas las caracter\u00edsticas de Write, incluida la sintaxis especial para formatear como Pi: 1: 4.<\/li>\n\n\n\n<li>Desventaja: la sintaxis especial para formatear es una \u00abmagia del compilador\u00bb, implementada espec\u00edficamente para rutinas como esta. Esto a veces es problem\u00e1tico, p. no puede crear su propia rutina MyStringFormatter (\u2026) que tambi\u00e9n permitir\u00eda la sintaxis especial como Pi: 1: 4. Por esta raz\u00f3n (y tambi\u00e9n porque no se implement\u00f3 durante mucho tiempo en los principales compiladores de Pascal), esta construcci\u00f3n no es muy popular.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-wp-embed is-provider-trasteando-por-vicio wp-block-embed-trasteando-por-vicio\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"wp-embedded-content\" data-secret=\"khvz9tKly6\"><a href=\"https:\/\/jorgeturiel.es\/?p=296\">Introducci\u00f3n al lenguaje Pascal moderno para programadores (Parte 2)<\/a><\/blockquote><iframe loading=\"lazy\" class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; clip: rect(1px, 1px, 1px, 1px);\" title=\"\u00abIntroducci\u00f3n al lenguaje Pascal moderno para programadores (Parte 2)\u00bb \u2014 Trasteando por vicio\" src=\"https:\/\/jorgeturiel.es\/?p=296&#038;embed=true#?secret=cVFk2M5V51#?secret=khvz9tKly6\" data-secret=\"khvz9tKly6\" width=\"600\" height=\"338\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>\n<\/div><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Mucha gente considera el lenguaje Pascal, como un lenguaje obsoleto, ya que en internet hay muchos recurso que hablan sobre el lenguaje Pascal, pero hablan sobre el \u00abviejo\u00bb Pascal. Michalis Kamburelis, creador del motor gr\u00e1fico Castle Engine, escribi\u00f3 una gu\u00eda muy concisa y sencilla, en la que muestra las caracter\u00edsticas de este lenguaje. En esta [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27,25,26],"tags":[22,23,21,24],"class_list":["post-277","post","type-post","status-publish","format-standard","hentry","category-lazarus","category-pascal","category-programacion","tag-delphi","tag-lazarus","tag-pascal","tag-programacion"],"_links":{"self":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/277","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=277"}],"version-history":[{"count":9,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/277\/revisions"}],"predecessor-version":[{"id":402,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/277\/revisions\/402"}],"wp:attachment":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=277"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=277"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=277"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}