Estou modelando uma linguagem de programação por diversão, e a sintaxe é fortemente influenciada pelas definições de função do Scala - especificamente.
Eu encontrei um problema de design porque minha linguagem não diferencia entre funções definidas por meio da def
sintaxe (métodos de classe) e funções anônimas atribuídas a valores (criados usando =>
) - remove as diferenças de implementação e comportamento .
O resultado é que as duas definições a seguir significam a mesma coisa:
def square(x: Int) = x*x
val square = (x: Int) => x*x
Não há motivo para o último formulário (atribuição imediata de função anônima) ser usado em qualquer situação normal - é simplesmente possível usá-lo em vez do def
formulário.
Ter essa sintaxe duplicada para definir funções nomeadas prejudicaria a ortogonalidade da linguagem ou algum outro aspecto do design?
Prefiro esta solução porque permite definições curtas e intuitivas de métodos e funções nomeadas (via def
) e definições breves de funções anônimas (usando =>
).
Editar: Scala faz diferenciar entre os dois - anónimo funções não são os mesmos como definidos com métodos def
em Scala. As diferenças são relativamente sutis - veja as postagens que eu vinculei antes.
fonte
However, assigning existing functions
parece estar faltando o final da fraseval
notação?fun
para definir uma função recursiva.def
é. É apenas um efeito colateral do fato de que uma função anônima, digamos,(x : Int) => x + 1
é um objeto, e os objetos podem ser atribuídos a valores comval f = ...
. Os projetistas da linguagem teria que sair de seu caminho para não permitir a sintaxe. Não é exatamente o mesmo que se esforçar explicitamente para oferecer suporte a duas sintaxes diferentes que fazem (aproximadamente) a mesma coisa.Respostas:
Eu acho que ter duas construções que significam a mesma coisa, mas com aparência diferente, deve ser mantido em um nível absolutamente mínimo em um idioma. Qualquer duplicação aumenta a dificuldade de ler (e, portanto, escrever / modificar o código) no seu idioma. A eliminação de toda duplicação é inevitável em um idioma que pode criar construções arbitrárias (por exemplo, a equivalência de iteração versus recursão).
Então, neste caso, acho que poderia ser melhor projetado aqui. Uma maneira única de definir funções faz mais sentido para mim. Nesse caso, parece que as duas declarações de escala que você tem realmente têm implicações ligeiramente diferentes, o que novamente provavelmente não é um bom design (provavelmente é melhor ter algo claro que indique quais são as diferenças, como uma palavra-chave).
De fato, você pode aplicar esse princípio não apenas às funções nomeadas, mas a qualquer função. Por que há alguma diferença na definição de funções nomeadas e funções anônimas? Em Lima , as funções são sempre definidas como este:
fn[<arguments>: <statements>]
. Se você quer que ele seja "chamado", você pode atribuí-lo a uma variável:var x = fn[<arguments: <statements>]
e se você quiser passá-lo para outra função anonimamente:function[fn[<arguments: <statements>]]
. Se você quiser que seja içado, faça-o constanteconst var x = fn[<arguments: <statements>]
. A forma única torna óbvio que eles significam a mesma coisa.fonte
const
causa içamento, mas faz todo o sentido. No JSfunction myFunc
, o içamento causa, masvar myFunc =
não o faz, o que talvez seja um pouco menos intuitivo, porque eles se comportam da mesma maneira.function fnName()...
forma cria uma constante, que é o que torna a elevação uma coisa válida a ver com ela. Javascript torna as coisas bastante confusas quando você usa o formulário,var fn = function anotherFnName()...
pois isso faz com que o nomeanotherFnName
não seja içado, mesmo que seja claramente constante.O que você postou é scala válido e funciona bem.
Dado que a duplicação não causou problemas com o scala (que eu saiba), vou dizer que também não será um problema para o seu idioma.
fonte
Eu encontrei uma diferença fundamental entre lambdas e
def
métodos no Scala - que ainda não tenho certeza se quero implementar. Eu tenho que fazer uma pesquisa mais aprofundada sobre isso e depois relatarei minha decisão.Essencialmente, apenas métodos podem
return
- e quando a palavra-chave é usada em um lambda, ela realmente retorna do método abrangente.Como eu disse, não tenho certeza se quero isso. Mas isso poderia ser justificativa suficiente para esta sintaxe. Ou talvez muito perigoso, porque diferenças sutis podem causar danos inesperadamente.
Detalhes
fonte