One of the cool features of our JavaScript interpreter
is that it supports anonymous or nested functions.
However, these features can be very hard to test, so let's try it out together.
You'll recall this Python example from before
where we had a nested function definition of greeter that we returned,
and the final output of this program would be "hello" "gracie".
I'm going to write this same program in JavaScript.
Aside from some minor syntactic differences, the content is the same.
We make a variable, greeting, initialize to "hola". Variable greeting is "hola".
We're going to define this makegreeter function of 1 argument called greeting,
define the makegreeter function of 1 argument called greeting.
Then we're going to make this sort of nested function greeter
that takes an argument, person, and here the local variable greeter is a function
that takes an argument, person.
So where in Python we used another def, in JavaScript we're using this function keyword.
Argument person is the same.
Instead of print we call write or document.write and we return the greeter.
Sayhello is a variable of makegreeter("hello"),
variable sayhello is the result of calling makegreeter on "hello"
and then we do it at the end.
So the real exciting part is here.
In JavaScript you can use the word function to make a new function anywhere
without really giving it a name, although we assigned it to the variable greeter
almost immediately.
So you can use it at the top level to make a function with a name,
or you can use it lower down.
See, here we just have function and then we're listing the arguments.
We didn't put a name in here.
This is sometimes called an anonymous function
because it doesn't immediately have a name.
So as a quiz, let's add support for those anonymous functions
to our JavaScript interpreter.
I'll write the first part, you fill in the key details.
Anonymous functions are expressions.
We know that since they can come on the right-hand side of something like this.
Anything on the right-hand side of a var or an assignment statement is an expression.
So there are a bunch of different types of expressions--
numbers, strings, binary operators.
Let's just handle the function part for now.
So as a running example, let's say we have a function of 2 variables, x and y,
that's going to return their sum.
The abstract syntax tree we get for that will have function
in this sort of identifier position telling us what this sort of node is,
then it will have a list of the parameters,
and then it will have the body list of statements.
And what I'd like you to do for this quiz is fill in these 4 blanks.
We want to return a particular value--
value corresponding to a function.
This is going to require you to think back to how we treated function definitions
and function calls earlier in our interpreter.
But here's a hint: A function was a for tuple containing the word function at the beginning
and then also listing in some order the body, the environment, and the parameters.
Fill it in.
JavaScriptインタプリタに無名関数や
入れ子になった関数を扱えるという機能があります
テストするのが非常に難しい機能なので
一緒に見ていきます
Pythonの例を思い出しますね
greeterという入れ子の関数を返して
最終的にhello gracieと出力されました
同じプログラムをJavaScriptで書きます
少々文法が異なりますが内容は同じにします
まず変数greetingをholaで初期化します
こちらも同様です
関数makegreeterを定義して
仮引数greetingを受けます
こちらも同様です
入れ子の関数greeterを作って
personを引数に取ります
こちらでは変数greeterに
1つの引数personを取る関数を代入します
Pythonではdefという予約語を使いますが
JavaScriptではfunctionを使います
引数のpersonは同じです
printの代わりにwriteを呼んで
greeterを返します
sayhelloにはmakegreeter(“hello”)の
返り値を入れます
こちらも同様です
そしてそれを終わりに呼び出します
最も重要な部分です
JavaScriptではfunctionという予約語を使って
ここでは変数greeterに代入しています
名前をつけなくても どこにでも
すぐ新しい関数を作れるのです
トップレベルに名前つきで
関数を定義することもできます
ここではfunctionのあと
すぐに引数を並べています
名前はつけていません
これが無名関数と呼ばれるものです
小テストです このような無名関数を
JavaScriptインタプリタで扱えるようにします
まず私が書くので完成させてください
無名関数は式です
このような代入文の右側に書けるものは
すべて式です
さまざまな種類の式があります
数値、文字列、二項演算などありますが
今は関数を扱います
x、yという2つの引数を持ち
その和を返す関数を作りましょう
これに対応する抽象構文木は
識別子の位置にfunctionと書いてあり
ノードの種類を示し
引数のリストを持ち
最後に本体の文のリストがあります
4つの空欄を埋めてください
ある値を返しますが その値は関数に対応します
インタプリタで関数定義や関数呼び出しを
扱ったことを思い出してください
関数は4項タプルでfunctionという文字列を持ち
本体や環境や引数をある順番で持っていました
Uma das coisas legais do nosso interpretador JavaScript
é que ele provê suporte para funções anônimas e funções aninhadas.
Entretanto, essas características podem ser difíceis de testar. Então vamos tentar isso juntos.
Lembre-se deste exemplo Python, que vimos antes,
onde temos uma definição aninhada da função greeter, que retornamos,
e a saída final do programa seria "hello gracie".
Vou escrever este mesmo programa em Javascript.
Fora algumas pequenas diferenças sintáticas, o conteúdo é o mesmo.
Criamos uma variável -- greeting -- inicializamos com "hola" -- a variável greeting é "hola".
Vamos definir esta função makegreeter, com um argumento, chamado greeting.
Definir a função makegreeter com um argumento, chamdo greeting.
Então vamos fazer esta função aninhada greeeter,
que tem um argumento -- person. E aqui, a variável local greeter é uma função,
que tem um argumento -- person.
Então, onde em Python usamos def, em JavaScript usamos a palavra chave function.
O argumento person é o mesmo.
Ao invés de print, chamamos write, ou document.write. E retornamos greeter.
sayhello é uma variável igual a makegreeter("hello") --
a variável sayhello é o resultado de chamar makegreeter("hello").
E depois fazemos isso no final.
Então, a parte realmente importante é aqui.
Em JavaScript, você pode usar a palavra function para construir uma nova função, em qualquer lugar,
sem ter que dar um nome a ela, mas nós a atribuímos à variável greeter,
quase imediatamente.
Então você pode usá-la no nível mais alto, para construir uma função com um nome,
ou pode usá-la no nível mais interno --
veja, aqui simplesmente temos function e depois listamos os argumentos,
não damos um nome aqui.
Isso é algumas vezes chamado de função anônima,
porque não tem um nome imediatamente.
Então, como teste, vamos prover suporte para essas funções anônimas
em nosso interpretador JavaScript.
Eu vou escrever a primeira parte, e voc6e preenche os detalhes chave.
Funções anônimas são expressòes.
Sabemos isso, já que elas podem vir do lado direito de algo como isso.
Qualquer coisa do lado direito de um var ou de um comando de atribuição é uma expressão.
Existem vários tipos diferentes de expressòes:
"numbers", "strings", "binops"...
Vamos tratar apenas a parte de funções agora.
Portanto, como um exemplo, digamos que temos uma função de duas variáveis -- x e y --
que retorna a soma das duas.
A árvore da sintaxe abstrata que obtemos terá "function',
nesta posição de identificação, nos informando o tipo do nodo,
e então terá uma lista de parâmetros,
e enTao o corpo -- uma lista de comandos.
E o que eu quero que você aça neste teste é que preencha esses 4 espaços em branco.
Queremos retornar um valor particular --
um valor correspondente a uma função.
Isso irá requerer que você pense novamente em como nós tratamos definições de funções
e chamadas de funções, em nosso interpretador, anteriormente.
Mas aqui está uma dica: uma função era uma tupla, contendo a palavra "function" no início,
e depois, em alguma ordem, o corpo, o ambiente e os parâmetros.
Preencha então.