Página 1 de 1

Usar funções em vez de procedures. Como fazer isso?

Enviado: 15 Abr 2008 09:00
por labaroazul
Bom dia, amigos! :* -:]

Para evitar o erro "Too many symbols" ao compilar o programa, foi sugerido a quem perguntou, em um outro tópico aqui do fórum, que fossem usadas funções no lugar de procedures.

Assim, em vez de:
DO CADASTRO //CHAMANDO O PROCEDURE DE CADASTRO
usar:
CADASTRO() //CHAMANDO A FUNÇÃO CADASTRO

E, em vez de
PROCEDURE CADASTRO
BLA, BLA, BLA
RETURN(.T.)
usar:
FUNCTION CADASTRO
BLA, BLA, BLA
RETURN NIL

Até aí, beleza.... :)Pos

Agora, como fazer para usar isso em um prg que chama outros prgs? :(Neg

Vou explicar melhor: Tenho um prg que eu chamo de Menu.prg, que chama outros prgs:

MENU TO OP
DO CASE
CASE OP = 0
EXIT
CASE OP = 1
DO CADCLI //CHAMA O PRG CONTENDO A TELA PARA CADASTRO DE CLIENTES.
CASE OP = 2
DO CADPRO //CHAMA O PRG DO CADASTRO DE PRODUTOS
ENDCASE

Já possuo, no mesmo Menu.prg, o comando

SET PROCEDURE TO FUNCOES

que chama o Funcoes.prg onde eu armazeno funções gerais do sistema, como as de controle de acesso em rede. Posso usar esse comando assim:

SET PROCEDURE TO FUNCOES
SET PROCEDURE TO CADCLI
SET PROCEDURE TO CADPRO
....? ´o)

Porque nesses prgs (Cadcli.prg e CadPro.prg) por exemplo, eu já coloquei assim:

FUNCTION CADCLI()
//AQUI TODO O PROCEDIMENTO DE CADASTRO, CONSULTA, ALTERACAO E EXCLUSAO DE CLIENTES E EXIBICAO EM UMA DBEDIT()
RETURN NIL

:f

Alguém pode me ajudar? :xau

Enviado: 15 Abr 2008 09:54
por gvc
Na verdade, vc coloca no seu arquivo rmk e lnk a informação de quais são os arquivos para compilar.
Vc não precisa colocar o "set procedure to ..."

No set procedure ou no arquivo rmk e lnk vc coloca o nome do arquivo prg, mas dentro do sistema vc coloca a chamada da função ou procedimento.

Outra coisa, procedure não retorna valor. Função deve obrigatoriamente retornar.

Se continuar com dúvidas, avise.

Espero ter ajudado. Boa sorte.

Enviado: 15 Abr 2008 10:18
por Maligno
Outra coisa, procedure não retorna valor. Função deve obrigatoriamente retornar.
Não. O retorno de função é opcional. A função retorna pura e simplesmente sem um RETURN ao final do código.

Re: Usar funções em vez de procedures. Como fazer isso?

Enviado: 15 Abr 2008 10:30
por Pablo César
labaroazul escreveu:que fossem usadas funções no lugar de procedures.

Código: Selecionar todos

Assim, em vez de:
      DO CADASTRO //CHAMANDO O PROCEDURE DE CADASTRO
usar:
      CADASTRO() //CHAMANDO A FUNÇÃO CADASTRO
Você ainda pode continuar chamando o seu módulo CADASTRO com o comando DO. Mas eu o utilizo quando este módulo for um PRG (aqui no seu exemplo: é o CADASTRO.PRG).

Código: Selecionar todos

E, em vez de 
      PROCEDURE CADASTRO
              BLA, BLA, BLA
      RETURN(.T.)
usar:
      FUNCTION CADASTRO
               BLA, BLA, BLA
      RETURN NIL
Aqui você entendeu essa idéia. Porém cabe ressaltar que as FUNCTIONs podem receber parâmetros e retornar valores de dentro dessas funções. Exemplo:

Código: Selecionar todos

// Aplicativo TESTE.PRG

SET DATE TO BRITISH
SET CENTURY ON
dDIA:=CTOD("25/12/0000")
QUEDIA:=VEJADIA(dDIA)
? QUEDIA

FUNCTION VEJADIA(dData)
Local VD:={"Domingo","Segunda-feira","Ter‡a-feira","Quarta-feira","Quinta-feira","Sexta-feira","S bado"}
ODIA:=DOW(dData)
VRET:=VD[ODIA]
RETURN VRET

// Fim do arquivo TESTE.PRG
possuo, no mesmo Menu.prg, o comando

Código: Selecionar todos

SET PROCEDURE TO FUNCOES
Isto você não vai usar mais, esta configuração. Pois ela serve para manter a compatibilidade de versões anteriores do Clipper e é obsoleta e descontinuada.

Se você tem módulo como aquele que eu mencionei CADASTRO.PRG, servirá para você entender que naquele PRG você tem a rotina de CADASTRO e nada mais. Agora se você precisar fazer rotinas comuns aos outros módulos como por exemplo aquele que eu exemplifiquei, então você poderia "armazená-las" no FUNCOES.PRG com as suas devidas decalrações de nome de cada função. Se a sua dificuldade está incluir este PRG de funções, aí ja seria uma questão de definição na hora de compilação. Eu por exemplo que uso muito o RTLINK e até com BLINKER eu faço uma arquivo .BAT, assim:

Código: Selecionar todos

@ECHO OFF
CLIPPER ARQUIVO_PRINCIPAL /B > LOG.TXT
IF ERRORLEVEL 1 GOTO ERRO
CLIPPER FUNCOES /B > LOG.TXT
CLIPPER HELP /B
IF ERRORLEVEL 1 GOTO ERRO
CLIPPER ERRORSYS /M /N
IF ERRORLEVEL 1 GOTO ERRO
RTLINK FI ARQUIVO_PRINCIPAL,FUNCOES,HELP,ERRORSYS,__WAIT,TIMESLIC LIB CT
ARQUIVO_PRINCIPAL.EXE
GOTO FIN
:ERRO
TYPE LOG.TXT
PAUSE
GOTO FIN
:FIN
O nome que aparece como ARQUIVO_PRINCIPAL, me refiro ao PRG principal que por consequente irá dar o nome do executável, mas caso que você queira dar outro nome é só colocar OUT OUTRO_NOME na linha do RTLINK ou BLINKER, como quiser.
nesses prgs (Cadcli.prg e CadPro.prg) por exemplo, eu já coloquei assim:

Código: Selecionar todos

FUNCTION CADCLI()
//AQUI TODO O PROCEDIMENTO DE CADASTRO, CONSULTA, ALTERACAO E EXCLUSAO DE CLIENTES E EXIBICAO EM UMA DBEDIT()
RETURN NIL
Na impede de você colocar estas funções no módulo CADASTRO.PRG.

"Too many symbols" também pode ser um excesso de uso de variaveis veja esta indicação: http://www.ousob.com/ng/clerr/ngd24b.php

Enviado: 15 Abr 2008 10:35
por Pablo César
Maligno escreveu:
Outra coisa, procedure não retorna valor. Função deve obrigatoriamente retornar.
Não. O retorno de função é opcional. A função retorna pura e simplesmente sem um RETURN ao final do código.
Sim mas o que talvez o colega quis dizer é que utilizando o retorno de funções não precisaria estar declarando variaveis novas e mais ainda do tipo PUBLICAS que consomem memória. Por isso eu também mencionei (sem ter visto seus posts) que dá para utilizar o retorno das funções. Se bem que utilizei um exemplo "não sintetizado", mas foi para dar exemplo e evidenciar o seu uso.

Enviado: 15 Abr 2008 10:49
por Maligno
Você interpretou errado, a meu ver.

O que o colega GVC disse foi "Outra coisa, procedure não retorna valor. Função deve obrigatoriamente retornar.", e isso não é verídico. O fato é: o uso de função não pressupõe o retorno de valor algum. Sequer exige um RETURN.

Enviado: 15 Abr 2008 11:38
por gvc
[Maligno]
... "Outra coisa, procedure não retorna valor. Função deve obrigatoriamente retornar.", e isso não é verídico. O fato é: o uso de função não pressupõe o retorno de valor algum. Sequer exige um RETURN.
Curioso...

Sempre recebi avisos do compilador que devo retornar valor no retorno de uma função, mesmo que seja Nil.
O objetivo das funções é retoenar um valor. Eu uso-as muito e sempre retorno algo, mesmo o Nil que não será usado.

O Clipper entende que acabou uma procedure ou função quando encontra a declaração de uma nova procedure / função / fim de arquivo.

Vou verificar...

[Pablo César]
O "DO nome_do_procedimento" era para manter a compatibilidade com o DBase. Da versão summer´87 em diante, isso não era mais necessario. Adimito que não lembro se o clipper´86 aceitava essa necessidade.
Assim como o "SET PROCEDURE TO nome_do_arquivo" foi mantido para manter compatibilidade com as primeiras versões do clipper. Vc informa no arquivo principal quais são os PRG´s que devem ser agregados ao sistema. Vc tb pode fazer isso em outros módulos, mas não é uma boa prática.
Como os Clippeiros "evoluiram" para outros métodos, isso não é muito usados atualmente. (Não quer dizer que não seja.)
Como os "linkers" evoluiram, o método de compilação tb mudou. Compilamos módulos individuais e não o sistema todo.
Lembrando que isso é uma prática. Nada impede de que o Clippeiro continue usando o "set procedure to ...". (cada louco com a sua mania. eh! eh! eh!)

Enviado: 15 Abr 2008 11:55
por Maligno
gvc escreveu:Sempre recebi avisos do compilador que devo retornar valor no retorno de uma função, mesmo que seja Nil.
Se você usar o switch /W para compilar, o compilador realmente reclamará a falta de um RETURN. Mas é apenas por quê ele "pensa" que algo está errado.
O objetivo das funções é retoenar um valor. Eu uso-as muito e sempre retorno algo, mesmo o Nil que não será usado.
Não exatamente. O real objetivo da função é modularizar o código. O retorno desta é uma opção a mais de uso para, entre outras coisas, aproveitar sua saída como entrada de outra função.
O Clipper entende que acabou uma procedure ou função quando encontra a declaração de uma nova procedure / função / fim de arquivo.
É isso mesmo. O que torna desnecessário o uso do RETURN. Mas lembrando que o /W, se utilizado, vai fazer o compilador "apitar". Eu nunca usei esse switch.

Enviado: 15 Abr 2008 21:46
por vagucs
Desse assunto entendo.

Bom, em Delphi, como o maligno mesmo sabe, a logica é este, FUNCTION sempre retorna um valor, e PROCEDURE não.

A um tempo atrás, o clipper summer, tinah esta diferenciação, tanto que se você criasse um sistema com PROCEDURES retornando algo, com um grande numero de procedures, poderia verificar alguns caracteres estranhos na tela, coisa que nunca impediu nenhum sistema de rodar, se fizer o contrario tambem, criar muitas FUNCITIONS sem colocar um return nelas, nem que seja RETURN "" (Nil).

No Clipper 5.x para frente, existem os 2 comandos (Óbvio), acho que mais para compatibilidade do que para qualquer outra função. Quando criei o DClip eu estudei a estrutura toda do arquivo e até mesmo qual a diferença fisica no EXE entre o comando PROCEDURE e FUNCTION, e verifiquei que, se você usa o clipper 5.x, independente de usar FUNCTION ou PROCEDURE, fisicamente no programa EXE final não tem diferença nenhuma, o código compilado é sempre o mesmo. Mas acho interessante, para questão de didatica do fonte, você padronizar, FUNCTION é porque tem retorno e PROCEDURE é porque não tem.

Enviado: 16 Abr 2008 17:33
por ABeltrani
Pessoal, boa tarde !

Uma pequena dúvida:

RETURN (.T.) ou RETURN .T. ?

É a mesma coisa ?

Enviado: 16 Abr 2008 17:52
por Pablo César
Sim é a mesma coisa, colega.

Enviado: 16 Abr 2008 20:14
por Maligno
Os parênteses tem apenas três funções: forçar o compilador a avaliar uma expressão numa ordem de precedência diferente do padrão E/OU melhorar a legibilidade do código E/OU expressar frescura. :)

Enviado: 16 Abr 2008 20:45
por vagucs
No clipper o parâmetro sempre indica que a expressão deve ser acumulada no Stack antes do proximo comando. Assim na versão 5.x podemos executar uma wave numa string

&("VAR")

Por exemplo, pois o parentese faz com que VAR seja acumulado no astack e o wave(macro) seja executado nele.

No summer isto nao era suportado.

Enviado: 16 Abr 2008 21:14
por Netavin
Maligno escreveu:Os parênteses tem apenas três funções... :)
... APENAS tudo isso!??? eheh

[]´s

Netavin

Enviado: 17 Abr 2008 09:25
por Pablo César
Adicionando ao seu comentário (um pouco sarcástico do Netavin). O parêntese é um indicador de agrupamento e também identifica uma chamada de função.
vagucs escreveu:o parentese faz com que VAR seja acumulado no astack e o wave(macro) seja executado nele
O que seria desnecessário para esta ocasião, não é Wagner ?

O NG em português fala sobre "Argumentos de comando":
Nas versoes anteriores do Clipper, bem como em outros dialetos, as variaveis macro geralmente eram utilizadas para especificar os argumentos de comandos que exigiam valores de texto literal. Isto incluia todos os argumentos de comando de arquivos, bem como comandos SET com argumentos de comuta. Nestes casos, agora você pode utilizar uma expressao estendida no lugar do argumento literal caso a expressao esteja entre parênteses. Por exemplo:

xcDatabase = "Invoices"
USE &xcDatabase.

pode ser substituido por:

xcDatabase = "Invoices"
USE (xcDatabase)

É importante utilizar expressoes estendidas, em especial se você estiver usando variaveis locais e estaticas.
Quando as variaveis macro sao transformadas em cadeias de caracteres, os nomes das variaveis macro ficam ocultos na string e nao sao compilados.
Mas em sintese não afeta na situação indaga pelo colega ABeltrani.