Monthly Archives: December 2015

Generic static fields — see you next year

I wanted to make a mental note at the end of 2015 — “feature freeze”. It won’t happen, I cannot make my mind what is the right choice.

The natural decision would be to copycat C# — each constructed type has its own copy of static fields which allows to use generic static fields. Resharper wiki warns about this approach — “in the vast majority of cases, having a static field in a generic type is a sign of an error” ¹. We can find simpler one in Java (more for historical reasons than technical, but still) — it does not support generic static fields and it shares static fields among all constructed types. Scala takes another angle for the same model — since static data can live only in companion objects and they cannot have type parameters the issue is solved by design. As for Swift it is an open question because as the error message says static fields are “not yet supported in generic types”.

C# has some peculiarities — till now I didn’t figure out why C# makes instances of static constructor (see Accelerated C# 2010 by Trey Nash, p.263). Skila would have to add its own because of static variables in generic methods. I feel really insecure here so I wonder whether C# model is worth the effort?

A memento from C++ world:

The original intention of C++ template support envisioned a use-directed automatic instantiation mechanism that required neither user intervention nor multiple instantiations of the same file. This has proved considerably more difficult to achieve than anyone at the time imagined (see [STROUP94]).

— Stanley B.Lippman, Inside the C++ Object Model

Sure, it is not the same issue, over 22 years passed, nevertheless I still have the chills. Until I have firm knowledge or burning desire for this feature I’d better follow Swift footsteps — not supported. Yet.


¹ I was curious what “vast majority” means so I contacted the author of that entry, Dmitri Nesteruk. As it turned out it doesn’t translate to any numbers, it was just a generalization based on the nature of C# model.

Advertisement
Tagged , , , , , , , , , ,

Into the valley of nulls

Working on the new design of null brought so many challenges that I didn’t implement any special support for them in generic types — the concept is pretty alien to me and I don’t know what to fix because nothing is broken yet.

Skila features stackable null values with no performance penalty compared to regular values. It means indexOf for String does not use magic value -1 any longer, the pair first/firstOrDefault of the collection is the pattern of the past. All you need to return is optional value.

You can work with optional values safely:

let i ?Int = null;
test(i); // compile error

def test(i Int) Void ...

Can you guess why you will get compile error? Type mismatch? Close, but not enough — types do match here but conditionally (there is precisely one level of Option<T> difference) and this means the entire call is executed conditionally as well. Statement became expression with the outcome failure or success which has to be read or explicitly dropped. Like here:

let i ?Int = null;
_ = test(i); 

def test(i Int) Void ...

For the record there is no magic here, just regular error:

let i ??Int = null;
test(i); // classic type mismatch

def test(i Int) Void ...

There was no need to introduce special syntax for optional chaining (besides there would be asymmetry between optional caller and optional argument), so instead of clunky “?.” you write:

var s ?String = null;
s = s.toLower(); 

which is equivalent of:

var s ?String = null;
s = s is null ? null : s'value.toLower(); 

Unlike pre-6.0 C# no exception is thrown, unlike C# 6.0 the syntax is clear, and unlike Icon you cannot simply ignore the optional execution. Time will tell whether such approach is indeed a winner.

Tagged , , , ,

Bringing order to the assignments

I changed the assignments several times — and it is not surprising when you consider the various approaches of the programming languages. Lately I reverted them to “statements only” because of Swift, to change it back to the expressions because of PHP. However the argument statements vs. expressions was not my only concern — I have learned (from Fluent Python by Luciano Ramalho) that Python switches the meaning of the compound assignment depending which operator was implemented in a given type.

m += u;

Will m value be changed in place or will a new object be created and bound to m? It is impossible to say without looking at the m type implementation. Not that I was about to make similar mistake, but I realized that compound assignment should scream its meaning so there were no doubts what it does.

I also have read an interesting complaint about the assignment symbol itself:

A notorious example for a bad idea was the choice of the equal sign to denote assignment. It goes back to Fortran in 1957 and has blindly been copied by armies of language designers. Why is it a bad idea? Because it overthrows a century old tradition to let “=” denote a comparison for equality, a predicate which is either true or false.

I understand the point but I don’t share the reservation — we don’t have the freedom of the blackboard, only the keyboard with just a few symbols. The tool dictates the possibilities.

Enough about the problems — let’s talk about solutions. The assignment is written all over the code — so it has to be single character, for me there is no debate here really, besides there are too many languages which use this syntax, the winner is:

s = "hello world"; 

I would like to compare values with operators like “>” or “<=”, so testing value equality has to be written with:

if s == "hello world" then
  ...

Here is the rub — assigning reference is done with single “equal” sign, while testing the value is done with the doubled sign. Well, far from perfect I know, I know.

Optional assignments work only within conditional structures:

if s ?= tryHello() then
  ...

When tryHello returns null — variable s will not be altered and the true branch of if will not be executed. When tryHello returns real value, the reference to that value will be assigned to s and the execution will proceed.

Assignments used as an expressions proved to be useful, however the usual syntax leads to errors and countermeasures such as yoda conditions. Scala ¹ and Swift ² are examples of the languages that dropped the support for assignment expressions, but why remove semantics when the problem lies in syntax:

a = b := c; // with expression
b = c; // just statements
a = c;

Please note that there is just one edit distance point between “=” and “==”, while there are two points between ”:=” and “==”. It does not guarantee the safety, but it should be sufficient protection against misspelling.

I would like to remove compound assignments to be crystal clear there is no alteration of the value in place (there should be another operator for this). Of course repeating left hand side of the assignment (with possible subexpressions) is a nasty thing to do. Unless ³:

msg = "world";
msg = "hello " + $;

On the expense of little more typing user will get way more power — I think it is a fair exchange.


¹ What is the motivation for Scala assignment evaluating to Unit. It seems Scala was supposed to evaluate assignments to their left hand side value, not right.

² What was the reason for Swift assignment evaluation to void — do you know the answer?

³ The idea is not mine (as usual), but I cannot recall where did I read this, I will update this post as soon as I find out.

Tagged , , , , ,

foreach can be the answer

C# foreach loop is undoubtedly elegant, however in daily use it is not efficient or versatile — I don’t envy the developers using the languages which dropped indexed for loop without solid substitution. When you need an index — usually you have to zip your collection with a range. Testing first or last element — a bit less common scenario — you need to add an extra scope with appropriate variables by hand. And adding nested continuation loop… — this is why I am glad C# still supports C-loop.

In Skila though, I am close to cover all the cases in a right way and have good reason not to introduce the old way of iterating. The performance is intact and you have concise syntax, starting from the basic form:

for elem in collection do
  ...
end

With just a control label (for any kind of loop — for, while and repeat-until) you can solve the common tasks:

loop: for elem in collection do
  stdOut.writeLine(loop.isLast); // `for` only
  stdOut.writeLine(loop.isFirst);
  stdOut.writeLine(loop.index);
  break loop; // here label is optional
end

All three “members” are just plain variables — when not used by the user, they are scrapped from the code, when used — they don’t leak. Nested loops are less of the rush (besides, they require more internal rewiring) so I’ll add them sometime in the future.

Tagged , ,

When IntelliSense slows you down…

I use mostly Visual Studio 2010 to develop Skila but one thing that drives me crazy is the performance of IntelliSense with remote files. It does not work slower — it crawls. I don’t know why it is so hard to read the file and allow to edit it, but since even scrolling through the file is lagging I was happy to notice Xamarin Studio developers figured it out. It is not as mature as VS, it lacks reliable debugger, but when it comes to initial implementing ideas I use XS now. The acronym is much better for sure.

Xamarin Studio is available for Mac and Windows, for Linux we have MonoDevelop. The difference is (quote) — “Xamarin Studio (…) is a bundle of MonoDevelop along with Xamarin iOS/Android plugins and branding”.

Tagged , , ,

Mind your own data — take two

Thanks to aliases implementing single field per property was not hard, but there were still limitations:

def first Int
  var _first Int; 
  get: return field; // `field` is a local alias to `_first`
  set: field = value;
end
def second Int
  var _second Int; 
  get: return field;
  set: field = value;
end

Because constructor has to reach each of those internal fields, their names have to be unique within entire class. On the other hand with uniform aliasing inside property only single internal field is supported.

I might not borrow from Ada a lot, but after reading Programming in Ada 2012 by John Barnes one idea made its way to Skila. I cannot write such constructor:

def init()
  first._first = 0;
end

Because Int type does not have _first member. But I could write:

def init()
  first'fields._first = 0;
end

Apostrophe instead of regular dot means I ask for an attribute (or meta information, or compile time information). The terminology currently is not so important, the important fact is this extra syntax allows properties to have truly internal fields, and since I always wanted to name all the fields just field (easier copy&paste) I can finally do it:

def first Int
  var field Int; 
  get: return field; 
  set: field = value;
end
def second Int
  var field Int; // same field name
  get: return field;
  set: field = value;
end
def init()
  first'fields.field = 0;
  second'fields.field = 0;
end

Did I just introduce new syntax to solve a corner case? Yes, I am aware of that — but reflection in other languages shows it should survive.

Tagged , , , ,

Unlearning static variables

Back in C++ days from time to time I used static variables and it is annoying to me that in C# when I need small cache or something like this I cannot pin it to the method, but I have to pollute entire class with the implementation information — “hey, I use cache, come on and break it”. After reading the explanation why C# does not have static variables I am even more convinced you cannot really substitute it with hope and crossed fingers.

Consider how Skila does it:

class !TreeNode
  static var counter Int = 0; // this is a field
  let id Int;
  def init()
    id = counter++;
  end
end

Well, no magic here, I want to have id field per each object I create, so I need to have a global (per type) counter. This is C# style, every method can now interfere with the field counter and I definitely would like to avoid it. Let’s fix it:

class !TreeNode
  let id Int;
  def init()
    static var counter Int = 0; // this is a field
    this.id = counter++;
  end
end

The only difference is scope, and thus the visibility of the counter field. Since no other method can see it, no other method can mess with it (which gives a little bonus — the name is taken only within the method). However what the field sees didn’t change a bit — you still cannot initialize a field with local data, exactly as before.

Oh, right, this post is about “static variables”, not “static fields” — well, you can call them “static variables” now.

Tagged ,