9

I am modelling a programming language for fun, and the syntax is heavily influenced by Scala - specifically function definitions.

I have encountered a design problem because my language does not differentiate between functions defined via the def syntax (class methods) and anonymous functions assigned to values (created using =>) - it removes the differences in both implementation and behaviour.

The result is that the following two definitions mean the same thing:

def square(x: Int) = x*x

val square = (x: Int) => x*x

There is no reason for the latter form (immediate anonymous function assignment) to be used in any normal situation - it's simply possible to use it instead of the def form.

Would having such duplicate syntax for defining named functions hurt the orthogonality of the language or some other design aspect?

I prefer this solution because it allows for short and intuitive definitions of methods and named functions (via def), and short definitions of anonymous functions (using =>).

Edit: Scala does differentiate between the two - anonymous functions are not the same as methods defined with def in Scala. The differences are relatively subtle though - see the posts I linked before.

12
  • However, assigning existing functions seems to be missing the end of the sentence
    – Izkata
    Jun 21, 2014 at 4:25
  • 1
    Can you define recursive functions using your val notation?
    – Giorgio
    Jun 21, 2014 at 10:06
  • 2
    I verified that this is possible in Scala too. In SML it is not and you have to use fun to define a recursive function.
    – Giorgio
    Jun 21, 2014 at 15:39
  • 3
    The second form isn't really a special syntactical structure, the way def is. It's just a side effect of the fact that an anonymous function, say (x : Int) => x + 1 is an object, and objects can be assigned to values with val f = .... The language designers would have had to go out of their way to disallow the syntax. It's not quite the same as explicitly putting in the effort to support two different syntaxes that do (approximately) the same thing.
    – KChaloux
    Jul 16, 2014 at 19:09
  • 3
    The major benefit of doing something more than one way in a language is it is a great way to start unproductive religious debates which distract from the real problems (Thinking C++ here) .......
    – mattnz
    Jul 16, 2014 at 22:10

3 Answers 3

3

I think that having two constructs that mean the same thing but look different should be kept to an absolutely minimum in a language. Any duplication increases how difficult it is to read (and thus write/modify code in ) your language. Eliminating all duplication is unavoidable in a language that can create arbitrary constructs (for example, the equivalence of iteration vs recursion).

So in this case, I think it could be designed better here. A single way to define functions makes the most sense to me. In this case, it sounds like the two scala statements you have actually do have slightly different implications, which again is probably not good design (probably best to have something clear that states what the differences, like a keyword).

In fact, you can apply this principle not only to named functions, but to any function. Why have any difference in defining named functions and anonymous functions? In Lima, functions are always defined like this: fn[<arguments>: <statements>]. If you want it to be "named" you can assign it to a variable: var x = fn[<arguments: <statements>], and if you want to pass it in to another function anonymously: function[fn[<arguments: <statements>]]. If you want it hoisted, make it constant const var x = fn[<arguments: <statements>]. The single form makes it obvious that they mean the same thing.

2
  • That's quite interesting that const causes hoisting, but it makes perfect sense. In JS function myFunc causes hoisting, but var myFunc = does not, which is perhaps a bit less intuitive because they behave pretty much the same otherwise.
    – mpen
    Apr 12, 2016 at 5:52
  • 1
    @mpen Yeah, actually javascript essentially does the same thing. the function fnName()... form does in fact create a constant, which is what makes hoisting a valid thing to do with it. Javascript makes things pretty confusing tho when you use the form var fn = function anotherFnName()... since that makes the name anotherFnName not hoist, even tho its clearly constant.
    – B T
    Apr 12, 2016 at 21:36
2

What you've posted is valid scala and works fine.

Given that the doubling hasn't caused issues with scala (to my knowledge), I'm going to say that it won't be a problem for your language either.

1
  • 1
    It is valid in Scala, it mostly works the same, but it does not mean the same thing - and if you'd make more complex examples (type polymorphism is not available for anonymous functions e.g.) - the differences would become more apparent.
    – jcora
    Jun 21, 2014 at 8:19
2

I've found a fundamental difference between lambdas and def methods in Scala - that I am still not sure whether I want to implement. I have to do further research on it and then I'll report back on my decision.

Essentially, only methods can return - and when the keyword is used from a lambda, it actually returns from the encompassing method.

As I've said, I'm not sure whether I want this. But it could be justification enough for this syntax. Or maybe too dangerous because subtle differences can unexpectedly cause harm.

Details

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.