Tag Archives: methods

Recursive and ancestor calls — again

I‘ve just brought self and super calls back — more about these features in my previous post about them.

I am just not happy how super is implemented currently — I was forced to add initial stage of scanning all the signatures of types and functions in order to compute function derivation tables. So when I hit the body of the function — during the second stage of processing — I am able to bind super properly.

Advertisement
Tagged , ,

Towards real OOP — contravariance

I wonder if the boom of dynamic languages is not the effect of the incorrectly stated limits of statically typed languages like Java or C#.

It is pretty basic, but anyway:

interface Contract
  def compute(input String) Object;
end

Interface is a contract indeed — in this example we say that if you refine compute you should be able to tackle with String in input and Object in output. But let’s say we write:

class Worker refines Contract
  refines def compute(input Object) Int •••
end

Did we just violate the contract of the interface? No — we were supposed to produce Object, and Int is Object. We were supposed to cope with String in the input and we do even better — we handle all possible types (nothing is higher in type hierarchy than Object). We fulfilled the contract and added a bonus for those who use Worker type directly.

Well, I cannot speak for other languages, but Skila supports both sides of the refinement.

Tagged , ,

Twin methods

One of the patterns you can see in many languages are paired methods — modify itself, and the other one — create new instance and modify it. For example, it could be the case of any sequence:

// modify itself
def !reverse()
  •••
end

// return the modified version
def reverse() 'Self
  let clone = this.copy();
  clone!reverse();
  return clone;
end

The body of the first method of course varies, but the second one is always the same and there is no point in writing it manually. In Skila you write the first method and you will get the second one automatically.

Tagged ,

Evolution of a method

My understanding of the difference between getter method and getter property is the latter is the attribute of given type, something that you can just read. The former on the other hand is something you (painfully or not) compute.

It really annoyes me that in C# you have for example the method Count for IEnumerable (granted, as an extension) and you have Count property for such collection as List.

Let’s think in terms of refinement — when you have a method in your base type you can refine it in any derived type, but if at some stage you could guarantee no actual computation takes place you would be sending the wrong signal. Internally you have just a fetch operation, for the outer world you are still struggling with some number crunching. That is why Skila allows to refine a method as a property.

Dead simple:

interface Sequence<out T>
  // here we compute
  base def count() Int •••
end

class !Array<T> extends Sequence<T>
  // here we just read
  extends def count Int •••
end

And to make using properties as pleasant as possible Skila goes the opposite way than Scala — it is possible to call a property like a function but not the other way around:

let seq ~Int = [ 1, 2, 3 ];
_ = seq.count();
// invalid in Skila, valid in Scala
_ = seq.count; 

let coll [Int] = [ 1, 2, 3 ];
// both target the property
_ = coll.count(); // invalid in Scala
_ = coll.count; 
Tagged ,

What’s cooking — type generics and method’s zoo

I’ve just finished generics with type parameters, no surprise since I already implemented symbol generics. So far Skila does not have constraints, but I prefer to cover more ground in order to have working language in hand. Collections (and passing them around) is my next step.

Since this will take some time, I might make a break and add static virtual methods. You can say — “what? How a static method can be virtual”. Well, in C++/C# it cannot, because it was implemented that way. All it takes is one look from different perspective — take a regular virtual method and limit its access to static features only. Here you have it — static virtual method.

It is not a feature I will die for, but I too often bump into a problem which could be nicely solved having static virtual method and its cousin — pinned method (new concept), static or not. Pinned method is just like virtual one but it is erased with each new class in hierarchy, meaning once you add it somewhere you have to redefine it in each descendant class. This is pretty similar to pinned constructors (which are already implemented in Skila).

With such arsenal you can finally decide what is better for you, static factories or per instance, you can handle some traits of the class (type) with static methods. Nothing revolutionary, just more freedom and flexibility.

And since there is already so much variety why not add yet another one, with even more limited access — actually with no access at all. Function/method which relies only on its parameters with no side effects, pure function. We’ll see…

Tagged , , , , , ,

Exposing field’s methods

At least this feature I made on time as planned — similarly to un-shadowing the hidden methods, you can expose field’s methods. From time to time I have to either expose entire field (bad, but I am lazy) or I have to manually write a bunch of proxies — this is gives solid code but it is bad as well, because not productive. For fast prototyping, or for cases when you just need few methods from a field — exposing is the best pick. For example:

def main() Int
do
  var bar = new Bar();
  return bar.single();
end

struct Foo 
  def single() @Int = 1;
end

struct Bar 
  var foo Foo = new Foo();
  using foo.*;
end

The last directive — “using” — exposes given methods. This particular call is maybe an overkill because it exposes all methods, but is up to user which variant she/he uses. There are 3 more:

  using foo.single(*);
  using foo.single();
  using foo.single;

As one can see they are consistent with un-shadowing — from the first to the last one, we see exposing all “single” methods, exposing one particular “single” method (here: parameterless), and exposing “single” method under condition there is only one.

The call “bar.single()” is correct because Skila compiler automatically creates a proxy method for every “using” directive. Maybe in future it will be optimized and such call will be simply translated (redirected in compile time). However as we know “premature optimization is the root of all evil” so I’d better move to other, still green, pastures…

Tagged , ,

All little Saturday things

I confess — I am a traitor. Over a week ago I enrolled in Coursera course “Discrete Optimization” by Prof. Pascal Van Hentenryck and it is frustratingly interesting if I may say that. Since I love computational challenges I was hooked in since the first assignment. I tried to keep the weekend only for Skila, but I failed — writing one thing, and thinking about other makes no sense, so I switched and worked on DO almost entire Sunday. But don’t despair, I am a thorough guy, I wrote down how many hours I borrowed from Skila.

It doesn’t mean I did nothing — however only a little additions and improvements:

  • I optimized backend in case of non-virtual types (simply no virtual table),
  • in backend layer interfaces are classes with empty methods — this allows to safely call a method when derived class hides it,
  • I added standalone functions — this required surprisingly some work,
  • I already mentioned covariance when it comes to polymorphic methods,
  • Skila supports 4 types of expressing the base for numbers like in Python — “124” for decimal, “0xCAFE” for hexadecimal, “0o57” for octal and “0b010101” for binary,
  • numbers can be expressed with padding as in Ruby — “450_010” is exactly the same as “450010” only reading is easier,

Next point is exposing back shadowed methods — I have in mind three cases:

using base::foo(Int);
using base::foo(*);
using base::foo;

The first one brings up method foo with given signature, joker “*” in the second line brings all foo methods. And third one is a shortcut — if there is only one method foo in inherited class it will be brought up. If there are more — compiler will give you an error.

And that’s all for the Saturday, I am running back to DO assignments…

Tagged , , , , , , , , , , , ,

Using context of method call

I am reading “The Ruby Programming Language” by David Flanagan, and Yukihiro Matsumoto — a piece about indexing a string. In Ruby to get a character from a string counting from the end of it you can use negative index, for example:

str[-5]

I am not the fan of such design, because in every language there is some valid range of indices and such approach doubles it. You have to be twice as much thorough in Ruby to make sure negative index is not a side effect of some computation. And negative numbers don’t come for free — it is one bit less for the digits.

And since just a day before I wished for having some reference to a caller when using call chaining altogether it gave me an idea — why not add to Skila simply a call context? Indexing a string could look like this:

str[\length-5]

Backslash (from top of my head) would switch context to caller, so any expression valid for it, would be valid in a call as well. Such feature could bring more flexibility to call chaining (I love this style except when I have to debug it).

I am not sure about it, but at least it is worth remembering, thus I posted it.

Tagged ,

Recursive and ancestor calls

The problem with recursive calls is they look the same as regular calls to a function — i.e. you have to specify the name of the function and arguments. The obvious shortcoming is writing recursive lambda — in languages like C# you cannot do this. The second one looks trivial but distracts me — when I don’t have too elaborate function, let’s say 3­–5 lines, and I have to write another, very similar, one. Creating unified, more general, function for such short form is an overkill, so in all cases I remember I copy&paste the code changing important bits. But every time I do this, I have to pay special attention if I changed the recursive call — otherwise my program would be compiled without any error, yet this would introduce a bug into the code.

Skila forbids recursive calls by function name — you have to call “self” for recursive call. “self” does not mean “function(s) with this name”, it means “this function”.

This improves distinction when reading the code — if you see “self”, you know automatically there is recursion involved. If not — it is regular call. In the second case, the workflow could still be recursive (via cross calls), but checking this is out of scope of compiler (and there is no purpose anyway).

There is also another type of call with improved visual factor — a call to closest base method in class inheritance tree. When writing descendant “SayIt” method instead of using the name:

base.SayIt("hello world");

call “super”:

super("hello world");

and the “same” method will be invoked, but implemented in ancestor class.

Tagged , ,