Closed barbozafernando closed 3 years ago
Bom, testando algumas coisas aqui, percebi um detalhe. No exemplo acima, como função de callback, eu chamo function
ao invés de funcao
.
Fazendo pelo jeito correto, que é isso aqui:
var array = [1, 2];
var novoArray = mapear(array, funcao(item){ return item * 2 });
Retorna os seguintes erros:
[Linha: 1] Erro no 'item': Esperado ';' após expressão.
[Linha: 1] Erro no final: Esperado '}' após o bloco.
Boa noite @barbozafernando . Mais uma vez eu agradeço imensamente o interesse por nos ajudar no desenvolvimento da linguagem, peço desculpas pela demora também, eu estava fazendo alguns code reviews no código atual e acabei demorando mais do que esperava.
Vamos lá.
Vi que você falou sobre código duplicado no arquivo dist.js
e esse arquivo é o arquivo gerado automaticamente pela build para web via Browserify, por isso os códigos sempre estarão duplicados, já que o código fonte do interpretador é via Node.JS e o navegador não aceita código escrito apenas para o node sem um tratamento prévio.
Em relação a função mapear, ela ainda não existe na linguagem, então nativamente não ée possível chamá-la. Você está desenvolvendo ela? Caso positivo, acredito que o melhor jeito é construir no modelo de função interna, pois sinceramente desconheço uma maneira de fazer função aceitar função como argumento via interpretador. Há também um erro em var novoArray = mapear(array, funcao(item){ return item * 2 });
, falta o ; ao final do retorna, ficaria var novoArray = mapear(array, funcao(item){ retorna item * 2; });
Boa noite, @lucaspompeun.
Em relação a demora, fique tranquilo. Eu percebi que você estava ocupado com outras coisas e etc. Sem problema!
Sim, em relação ao dist.js
eu acabei percebendo depois hahahaha, my bad!
Ah ta, entendi. Cara. Na verdade, eu achei que já estava criando ela na forma de função interna. Peço desculpas.
E em relação ao erro do ;
eu acabei percebendo depois hahaha
Mas sim, Lucas, estou desenvolvendo a função mapear
. E novamente peço desculpas por não conhecer tanto do projeto ainda, pois as únicas coisas que sei, foram através do seu vídeo postado no youtube a um tempo atrás.
Bem, tem como você me dar um pequeno auxílio me dizendo aonde posso criar a função de forma nativa da linguagem? Pois como disse, eu achei que já estava fazendo isso hahaha.
Inclusive, aqui está o código:
globals.defineVar(
"mapear",
new StandardFn(1, function(array, callback){
if (!Array.isArray(array)) {
throw new RuntimeError(
this.token,
"Parâmetro inválido. O primeiro parâmetro da função, deve ser um array."
);
}
if (typeof callback !== 'function'){
throw new RuntimeError(
this.token,
"Parâmetro inválido. O segundo parâmetro da função, deve ser uma função."
);
}
let provisorio = [];
for(let index = 0; index < array.length; ++index){
provisorio.push(
callback(
array[index], index, array
)
);
}
return provisorio;
})
);
As funções internas são feitas no arquivo egua/src/lib/globalLib.js
Foi o que pensei. Criei justamente lá mesmo.
E pra testar na interface IDEgua não esquece de dar o npm run build-web
Cara, não to conseguindo fazer executar a função de callback. Tem alguma ideia aí?
Outra coisa, não consigo testar o método pelo terminal porque da esse erro.
E pela interface do Égua, não aparece nada. Eu acho que a função de callback não tá sendo executada, por isso não loga nada.
Tentei a solução:
globals.defineVar(
"mapear",
new StandardFn(1, function(vetor, funcao){
return vetor.map(function(){
return funcao;
});
})
)
Entretanto o interpretador da linguagem não permite a passagem de uma expressão segunda expressão para executar na função interna.
Por enquanto não consigo pensar em uma solução em termos de interpretador para isso :/
Aproveitando a sua boa vontade, @leonelsanchesdasilva hahaha, teria alguma dica pra esse caso aqui?
@barbozafernando Tenho sim.
mapear([5, 3], a * 2)
não vai funcionar porque o interpretador vai avaliar a * 2
na resolução do argumento. Neste caso, você precisa declarar uma funcao
primeiro.
egua> var f = funcao(a) { retorna a * 2; };
Aí implementei sua versão de "mapear" e tive o seguinte:
Não resolve a tipagem como "function". Resolve como "object". Mais precisamente, uma EguaFunction
.
Primeiro sua função tem que aceitar uma EguaFunction
e aí usar essa EguaFunction
durante a execução. Acredito que a mistura entre Egua e JavaScript esteja atrapalhando um pouco aqui.
@leonelsanchesdasilva o que você sugere para que uma EguaFunction
seja capaz de atender esse tipo de função interna?
@leonelsanchesdasilva o que você sugere para que uma
EguaFunction
seja capaz de atender esse tipo de função interna?
No momento, esse é o único empecilho. Tentei de várias formas, porém sem sucesso.
@lucaspompeun @barbozafernando Bom, callback
é uma classe, então tem um constructor:
Então implementei assim:
globals.defineVar(
"mapear",
new StandardFn(1, function (array, callback) {
if (!Array.isArray(array)) {
throw new RuntimeError(
this.token,
"Parâmetro inválido. O primeiro parâmetro da função, deve ser um array."
);
}
if (callback.constructor.name !== 'EguaFunction') {
throw new RuntimeError(
this.token,
"Parâmetro inválido. O segundo parâmetro da função, deve ser uma função."
);
}
let provisorio = [];
for (let index = 0; index < array.length; ++index) {
provisorio.push(
callback(
array[index], index, array
)
);
}
return provisorio;
})
);
Só que tem outro problema: callback
é chamado como função normal do JavaScript. callback
não é uma função do JavaScript. De novo, é uma EguaFunction
. Chamando do jeito em que está, temos este erro:
egua> mapear([5, 3], f);
Waiting for the debugger to disconnect...
readline.js:1170
throw err;
^
TypeError: Cannot read property 'line' of undefined
at Egua.runtimeError (D:\GitHub\egua\src\egua.js:90:32)
at Interpreter.interpret (D:\GitHub\egua\src\interpreter.js:779:23)
at Egua.run (D:\GitHub\egua\src\egua.js:65:21)
at Interface.<anonymous> (D:\GitHub\egua\src\egua.js:33:18)
at Interface.emit (events.js:311:20)
at Interface._onLine (readline.js:322:10)
at Interface._line (readline.js:699:8)
at Interface._ttyWrite (readline.js:1025:14)
at ReadStream.onkeypress (readline.js:198:10)
at ReadStream.emit (events.js:311:20)
Ainda que eu simplesmente troque a chamada de callback
por callback.call()
, eu teria outro problema. O primeiro argumento de callback.call()
precisa ser uma instância de interpreter
para executar corretamente. interpreter
não existe dentro de globalLib
por este motivo (src\interpreter.js
):
module.exports = class Interpreter {
constructor(Egua, baseDir) {
this.Egua = Egua;
this.baseDir = baseDir;
this.globals = new Environment();
this.environment = this.globals;
this.locals = new Map();
this.globals = loadGlobalLib(this.globals);
}
É uma construção bastante esquisita de objeto, devo dizer. globals
e Environment
são a mesma coisa, então deveria prevalecer apenas o nome environment
, evitando certa confusão e problemas de legibilidade.
Enfim, o interpretador inicializa o ambiente (Environment
, ou globals
), mas a referência do interpretador, que deveria ser passada para a função globalLib
não está sendo passada.
Então o que posso fazer é modificar o interpretador para inicializar as funções globais assim:
module.exports = class Interpreter {
constructor(Egua, baseDir) {
this.Egua = Egua;
this.baseDir = baseDir;
this.globals = new Environment();
this.environment = this.globals;
this.locals = new Map();
this.globals = loadGlobalLib(this, this.globals); // Passo o próprio interpretador para dentro da função que
// inicializa as funções globais.
}
E aí mudo a função que inicializa as funções globais para:
module.exports = function (interpreter, globals) { ...
Agora tenho o interpretador onde preciso, no caso, na chamada do callback
. A forma correta de chamar callback
fica assim:
let provisorio = [];
for (let index = 0; index < array.length; ++index) {
interpreter.locals.set(callback.declaration.params[0].name.lexeme, array[index]);
provisorio.push(
callback.call(
interpreter, [array[index]]
)
);
}
Por fim, temos:
Console da Linguagem Egua v1.1.0
egua> var f = funcao(a) { retorna a * 2; };
egua> escreva(mapear([5, 3], f));
[ 10, 6 ]
egua>
Eu posso abrir uma PR, se for o caso.
@leonelsanchesdasilva eu ficaria extremamente feliz com um PR seu, que solução genial.
Olá, tomei liberdade de criar o método
mapear
, cuja função é a mesma doArray.map()
do Javascript. Porém, estou com um problema.A linguagem não permite que uma função receba outra função como parâmetro. Alguém poderia me guiar nesse trecho ou corrigir pra poder dar pull?
Valeu!