Jump to content

[Debate] Tipos de dados em argumentos


nunopicado
 Share

Recommended Posts

Continuação deste tópico. @thoga31


Não é bug, é assim mesmo:

Não faria sentido que um procedimento recebesse como parametro um tipo de dados que não exista no scope onde ele será chamado.

Quando declaras var x:array of integer, estás a criar on-the-fly o tipo de dados, porque o array não é um tipo de dados em si mesmo.

Logo, tens de o declarar cá fora para que possa ser usado como parâmetro.

Quando aprendi Pascal, aprendi que os arrays devem sempre ser definidos como type.

Ainda que a linguagem aceite a criação on-the-fly, não é para usar em todas as situações.

É como um Record. Podes criá-lo directamente no VAR, mas regra geral, crias um type primeiro.

Edited by thoga31

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to comment
Share on other sites

Antigamente, era mandatório criar o tipo do array para ser declarado nos tipos de dados dos argumentos.

No entanto, actualmente isso já não acontece. Desta forma, não vejo por que motivo havemos de andar a usar uma perna de pau.

Repara: podemos criar on-the-fly e usar para umas coisas, mas para outras já não dá. Das duas, uma: ou dá para tudo ou não dá para nada. Assim eu nunca tenho a certeza de quando posso usar o tipo on-the-fly. "Na dúvida, crias." Então para isso que não tivessem criado esta possibilidade a meio gás. Assim parece que apenas o fizeram para tentar "calar" a crítica do Sr. Brian Kernighan.

Knowledge is free!

Link to comment
Share on other sites

O argumento do "dá para tudo ou não dá para nada" é tãããããoooooo fraquinho! 😛

Toda e qualquer instrução pode ser usada para umas coisas e para outras não. Faz parte. Logo que as situações em que dá e não dá estejam bem documentadas e explicadas, não é senão normal.

Senão, vejamos...

OOP. Coisa linda, adoro. Aquilo que conseguimos fazer com programação orientada a objectos, é brutal, em relação à programação típica.

DLL: Coisa linda, adoro. Permite-me modularizar um programa, com uma organização e flexibilidade tremendas. Mas...

Não suporta OOP.

Oooopsss... Acabe-se com OOP ou acabe-se com DLL.

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to comment
Share on other sites

Se uma DLL é programada em Delphi, o não suporte a OOP não faz muito sentido. A não ser que me dêem uma grande razão, vejo isto como algo limitante e bizarro.

Simples... É programada em Delphi, ou não é programada em Delphi... Não sabes, nem tens de saber!

Uma DLL é um formato aberto, que pode ser feito em "qualquer" linguagem. Logo tem de seguir o padrão.

Quanto ao bom motivo, que tal este:

Uma DLL, por definição, usa uma zona de memória diferente da do programa principal. Como tal, para fazer comunicação entre um e outro, é necessário que ambos os programas entendam os parametros de forma exactamente igual, e que o gestor de memória que os intermedeia, não se assuste também.

Ou seja, só é seguro passar tipos e estruturas standard, e uma classe OOP é tudo menos isso.

Podes passar os tipos primitivos, Record (logo que os elementos sejam tipos primitivos) e Interfaces (logo que os parametros de cada método das classes que implementam os interfaces sejam tipos primitivos).

Atenção uma coisa: Uma DLL não suporta OOP nos parametros que se passam de e para o programa principal.

Dentro da DLL, OOP é suportado à vontade.

Quem quiser e puder, pode usar antes BPL, uma DLL exclusiva para Delphi, e como tal, já permite compatibilidade total de parametros entre app e bpl.

Mas não são só vantagens... Ambos, app e BPL, têm de ser compilados com a mesma versão do Delphi, e todos os componentes partilhados têm de estar também na mesma versão.

Exactamente porque é preciso que comuniquem uns com os outros, e não há margem para erro!

Edited by nunopicado

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to comment
Share on other sites

Atenção uma coisa: Uma DLL não suporta OOP nos parametros que se passam de e para o programa principal.

Dentro da DLL, OOP é suportado à vontade.

Esqueci o resto a partir do momento em que li isto. Assim está bem, lol. Eu entendi que dentro da DLL não podias usar OOP. A passagem de argumentos é totalmente compreensível e nem meto em causa.

Mas voltando ao problema dos tipos mais simples (arrays), e fora aquilo que é o comportamento actual, o que achas? O tipo "array of integer" on-the-fly podia ser suportado mais extensivamente ou não? Eu digo que sim, acaba por fazer sentido 😛

Knowledge is free!

Link to comment
Share on other sites

Então, pego no teu argumento (dá para tudo ou não dá para nada), e respondo-te assim.

Quem diz array of integer, também podia dizer array of string.

Mas array of string é algo tão genérico que não seria nunca possível usar assim. Uma string pode ter 1 ou 2 bytes por caracter, dependendo do "código circundante". Pode ser Short, pode ser Wide, pode ser...

Directivas de compilação é outra que pode afectar os tipos de dados, até mesmo do tipo Integer, que como sabes, é um alias, e não um tipo fixo.

Muita coisa pode correr mal, por causa de um simples array of integer, na comunicação entre duas zonas de código.

Podia-se simplesmente cortar a hipotes de criar on-the-fly, mas para outras situações, até dá jeito.

Logo que saibas onde deves e não deves usar, acho que o sistema em vigor é muito bom!

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to comment
Share on other sites

Sinceramente não vi onde esses casos iam correr mal com um tipo on-the-fly.

O caso do Integer e das Strings não se coloca. O Integer é um alias, portanto, no momento de compilação, não vai ser SmallInt aqui e LongInt acolá. Os problemas dele estão na portabilidade entre compiladores. As Strings, havendo vários tipos, é uma questão de usar os tipos devidos. Em Free Pascal, pelo menos, o tipo "String" é o clássico. Se em Delphi é polimórfico, então isso passa-me ao lado.

O tamanho da String também nada tem a ver. Esteja num type ou on-the-fly, a problemática, a haver, mantém-se.

So what?

Edited by thoga31

Knowledge is free!

Link to comment
Share on other sites

As compiler directives podem mandar essa ideia ao ar... o que é no momento da declaração da variável externa pode não ser no momento da declaração do parametro.

Curiosamente, e apesar desta conversa toda, fui testar, e o Delphi XE3 já permite o array on-the-fly nos parametros! 😄

É só novidades! Se não me falha a memória, ainda no XE não dava para isso!

Edited by nunopicado

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to comment
Share on other sites

Tópico dividido.


O meu argumento "tudo ou nada" não foi bom, de facto.

Mas neste caso não vejo muita coerência. Estive a dar uma vista de olhos no guia de referência do FPC, e comparando com alguns usos de tipos "on-the-fly", aquele SetLength é um excluído do mundo aberto de tipos dissociados do type. 😕

Curiosamente, e apesar desta conversa toda, fui testar, e o Delphi XE3 já permite o array on-the-fly nos parametros! 😄

Isto já não é novo, e no Free Pascal já tem alguns anos.

Mas lá está: nuns casos dá, noutros não dá. Nos casos em que não dá, dos que vi até agora, os motivos para o não-suporte são inexistentes.

Quanto às compiler directives, situações complicadas surgem quando o programador é parvo, essencialmente. Se fôssemos por aí, as listas ligadas tinham de ser banidas: a quantidade de memory leak que pode haver, entre outras coisas, é algo assustador 😄

Knowledge is free!

Link to comment
Share on other sites

realmente vc poderia ter um metodo tipo:

unit Teste1;


{$H-} //string = sortstring
interface

procedure Teste(var a : array of string);

e tentar

unit Teste2;


{$H+} //string = ansistring
interface

uses Teste1;

var
 a : array of string;
begin
 Teste.Teste(a);//seria um problema.
Edited by nunopicado
GeShi
  • Vote 1
Link to comment
Share on other sites

Sim, era mesmo nesse sentido que eu falava...

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to comment
Share on other sites

A questão aqui é que utilizar array of <type> cria um tipo de dados anónimo. Ora, uma vez que em Pascal o type-checking é feito pelo nome dos tipos de dados (após aplicação de regras de conversão implícita, etc), faz algum sentido que não seja possível utilizar esse tipo de dados anónimo (que chamaste de "on-the-fly").

Se o Delphi XE3 suporta, tanto melhor, mas a justificação para que não se suporte tal sintaxe é a que forneci.

E reparem, faz algum sentido (apesar de ser inconveniente por vezes); reparem no seguinte código:

type
 TItem       = ... ;
 TPersonList = array of TItem;
 TFoodList   = array of TItem;

Se a compatibilidade de tipos de dados for avaliada pela estrutura dos mesmos, então podemos utilizar TPersonList onde nos pedirem TFoodList, ou em qualquer array of TItem. Uma vez que os tipos de dados são verificados pelo seu nome, tal situação é impedida -- algo muito bom para todos nós, que somos obrigados a pensar 2x nos tipos de dados que utilizamos.

Existe, no entanto, uma situação intermédia (possivelmente será a do XE3): nos locais onde for requerido um tipo de dados anónimo como array of TItem, poderão ser aceites tipos de dados estruturalmente equivalentes (como acontece com TPersonList, TFoodList), sem afectar as situações onde é pedido um tipo de dados específico (pelo seu nome), nas quais a estrutura deixa de ser considerada.

Pessoalmente, gosto quando um compilador se queixa que estou a utilizar um tipo de dados inválido, mesmo que seja estruturalmente equivalente -- se tem um nome diferente, é para ser utilizado noutras situações -- pelo que o comportamento "habitual" do fpc não me chateia muito. É uma questão de clareza, parece-me.

  • Vote 1
Link to comment
Share on other sites

Concordo Pedro.

Aliás, só descobri que o XE3 já dava por mero acaso, ainda não o tinha tentado antes.

O facto de não dar no FPC parece-me um não-problema.

"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Link to comment
Share on other sites

Existe, no entanto, uma situação intermédia (possivelmente será a do XE3): nos locais onde for requerido um tipo de dados anónimo como array of TItem, poderão ser aceites tipos de dados estruturalmente equivalentes (como acontece com TPersonList, TFoodList), sem afectar as situações onde é pedido um tipo de dados específico (pelo seu nome), nas quais a estrutura deixa de ser considerada.

Seguindo o exemplo

type
 TItem	   = ... ;
 TPersonList = array of TItem;
 TFoodList   = array of TItem;

Se tiveres uma funçao que peça um TPersonList nao podes passar uma variavel do tipo TFoodList nem do tipo array of TItem, tem de ser explicitamente do tipo TPersonList.

Link to comment
Share on other sites

Kline777,

Eu estava apenas a lançar uma hipótese para funcionar nuns casos e noutros não (eu nem sequer utilizo o Delphi XE3). Por outro lado, o exemplo que apresentei (e repara que o apresentei antes do parágrafo que citaste) servia apenas para exemplificar a questão da determinação de compatibilidade de tipos através do nome do tipo de dados.

Se tiveres uma funçao que peça um TPersonList nao podes passar uma variavel do tipo TFoodList nem do tipo array of TItem, tem de ser explicitamente do tipo TPersonList.

Parece-me bem que seja necessário utilizar explicitamente um TPersonList. Não vejo grande motivo para o compilador aceitar de ânimo leve um array of TItem ou TFoodList neste caso. Aliás, se estiveres seguro de que os tipos de dados são estruturalmente idênticos (compatíveis ao nível do seu bit-pattern), podes sempre fazer typecast como quem afirma que sabe o que está a fazer.

  • Vote 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.