My thoughts on UFCS

alextretyak

Administrator
Staff member
[This post is inspired by this article.]

This feature is nice, but I strongly believe that this should be denoted explicitly, i.e. if you want to call evenNumbers like this:
Code:
evenNumbers([1, 2, 3, 4])
then declare it such way:
Code:
F evenNumbers(Array[Int] arr)
   R arr.filter(n -> n % 2 == 0)
If you want to call it as [1, 2, 3, 4].evenNumbers(), then declare it this way:
Code:
F Array[Int].evenNumbers()
   R .filter(n -> n % 2 == 0)
And to call it as [1, 2, 3, 4].evenNumbers just remove parentheses:
Code:
F Array[Int].evenNumbers
   R .filter(n -> n % 2 == 0)

If you want to allow the user to use evenNumbers in any of these three ways, then you should write something like this:
Code:
F evenNumbers(Array[Int] arr)
   R arr.filter(n -> n % 2 == 0)

F Array[Int].evenNumbers()
   R evenNumbers((.)) // `(.)` means `self`, but this line can even be shortened to `R evenNumbers(.)`

F Array[Int].evenNumbers
   R evenNumbers((.))
 
Last edited:

Dani

New member
What's the reasoning behind this?
Also, I'd vote against the version without parentheses, because it's not clear from the code whether evenNumbers is a variable or a function.
 

alextretyak

Administrator
Staff member
What's the reasoning behind this?
Can you elaborate on what you mean by this?
UFCS feature in itself? Or my statement that this should be denoted explicitly? Or my proposed syntax?
Also, I'd vote against the version without parentheses, because it's not clear from the code whether evenNumbers is a variable or a function.
Mostly I agree with you, but there are some rare cases when this feature can be useful. Particularly, for extremely short functions, which call costs about the same as a variable access and which are inlined anyway.
For example, to get a length of an array in 11l you can write arr.len rather than arr.len(). Also there is arr.empty parentheses-less method, which is equivalent to arr.len == 0.
Or in the Nim programming language, there is arr.high, which corresponds to arr.len - 1.
I think all such functions should be called without parentheses to denote their ultra low cost.
 

alextretyak

Administrator
Staff member
Also parentheses-less methods can replace properties' getters (just like in Ruby):
Code:
T Value
   . String val

   F int_val=(Int new_val) // setter
      .val = String(new_val)

   F int_val // getter
      R Int(.val)

Value val
val.int_val = 10 // implicit call of `int_val=()` (setter)
print(val.int_val) // implicit call of getter

And if you vote against the version without parentheses, what do you think about properties (getters/setters)?
 

Dani

New member
Can you elaborate on what you mean by this?
Your statement that every such function definition should be denoted explicitly.
And if you vote against the version without parentheses, what do you think about properties (getters/setters)?
That's a very hard question. I'd have to think about that.
Very often they denote a very low cost operation, but they can also denote things that are lazily initialized, and I think it's fine, since the initialization happens only one time.
But since I haven't used properties in a language designed for high performance, I'm not sure I can actually answer this question.
 
Top