Move to Kotlin?

Maybe because I am “old” I very much appreciate @princec’s take on variable types. There may be a few situations where the use would be benign, where the type doesn’t matter and thus having to specify it is, indeed, “noise.” But I think it is legitimate to worry that the feature will be abused and overused.

I am reminded of the old saw “a place for everything and everything in its place.” Drives kids nuts, and for good reason: they are much more capable of remembering where everything is and don’t see the motivation. Since they are pretty much bounded to a smaller area than adults, it is much easier for them to keep track of things.

With age and increased responsibility, the amount of information that you can or care to clutter your head with gets much smaller. It definitely adds to the cost of context switching, with trying to move between multiple projects. Carrying trivial crap around like what the dang variable is or isn’t is an aggravating nuisance. It’s like having to continually stop for commercials when you just want to watch your movie. I am now experiencing the so-called joys and freedom of var with the JavaScript/VR project I’m working on, and am finding it a considerable annoyance with both debugging and with code-reading libraries and examples.

What is the term? Ah, here it is: technical debt

[EDIT, restatement of the controversy in terms of cognitive activity: is it more or less burdensome to mentally block out a bit of redundant “noise” than to carry additional facts in working memory? ]

If I weren’t interested in improvement I wouldn’t be so keen on Ceylon now, would I. Or Clojure, for that matter. (which I am)

Cas :slight_smile:

… and nor would I have been interested in generics. Nor Java in the first place. Nor would I be looking forward to value types, or reified generics.
I am not sure how you conflate my fairly clearly reasoned distaste for the concept of the var keyword with whether I want to “improve” or not, given that I’m clearly looking forward to all sorts of other changes (Hint: I don’t really need to improve myself much in the field of computer science - I’m already close to the top of the game I need to be in - further “improvement” won’t get me anywhere I want to be)

Cas :slight_smile:

I’ve been working in Kotlin for the last 5 months. It’s a joy. There is without a doubt a much faster idea to code time, and as a result code is cleaner and more functional. I didn’t read all the replies in this thread, but I did notice princec and phil’s thoughts on dynamic typing. If the issue is variable type not being obvious, IntelliJ will automatically add in “ghost text” that tells you the type of the variable where it is declared. This way, you don’t have to type (in the keyboard sense XD) it, but you can be sure what type it is when you write it or look at it again. Also, if there was any question at all about java interop, the audiocue library from phil works after just putting it in the library folder, as you would do on a java project. There is nothing else needed! It’s great! (both Kotlin and AC ;)) <- o shit the https://xkcd.com/541/ situation (edit - never mind it turns into an emoticon)

I’m not sure if anybody else mentioned this, but Kotlin has pretty strange generics. The “in” and “out” system is less intuitive than Java’s, I think, because the words don’t really mean anything from the start. Other than that, I have no complaints. 8000 lines in 4000, and less than a week of practice (not counting that I get from actually porting the code and then writing new stuff)

Also, h.pernpeintner, you need to be considerate. Just because he doesn’t agree with you doesn’t mean he doesn’t want to get better… he had (completely true) point that it’s often a result of practices being ingrained over the years that makes him (and phil) not want to change (not trying to be like haha you’re old :P)

I’m very excited about Kotlin too, but respect people who aren’t. The very nature of programming is that it tends towards efficiency anyways, so if Kotlin turns out to be very good (which I think it will), people will just use it. And it spirals upwards from there, accelerated by its java interop.

Princec actually brings up a good point, there’s 0 reason (from what I can think of right now) to declare the type of a variable and then have to retype the type when you’re trying to cast. You’re clearly in the camp of “less syntax”, so why is what Princec said hilarious? It seems that you two would actually agree on the casting point.

But the whole type debate - I have a love/hate relationship with dynamic typing. If I’m working on a small personal project where I can keep all of the object definitions in my head while working then I love dynamic typing. It’s not that much less typing, but it does save me a tiny bit of work that adds up over time. But on the flip side, if I’m reading someone’s code or I’m working in a corporate setting then absolutely, I want my types defined right there in front of me. It’s extremely painful to go hunt around a large codebase, connecting the dots and figuring out what type something actually is. Phil mentioned context switching and I completely agree with that - IMO its important that you give your mind a break and just let your work be as easy as possible. Hunting for types is trivial and is unnecessary work that you shouldn’t have to deal with when you’re trying to figure out the maze that large codebases can be.

I think there’s fairly clear uses for either dynamic or static typing. I love NodeJS and Java for vastly different reasons and use them in far different ways.

How about because having the same syntax for a standard assignment (which can’t throw a CCE) and a casting assignment (which can throw CCE) is a daft idea? Fine make it “less syntax” but at least make it an explicit action to move type checking to runtime.

Now if var in Java supports casts you’ll be able to just write the type once without duplicating syntax! :wink:

Very nice to hear AudioCue works with Kotlin!

I’m wondering if this means that Kotlin’s interop with Android means that AudioCue can be used with Android via Kotlin? There are basically just a couple IO functions (SourceDataLine and AudioInputStream) that rely on the javax.sound.sampled. Everything else in it is vanilla Java. I was assuming that for AudioCue to work with Android, it would be a matter of recoding the two IO points, and accepting the higher latencies that come with Android devices.

Suggestion that I might be afraid of change or stuck with ingrained practices is kind of hilarious. I hadn’t even see my first line of Java code until into my 50’s, something like 8 years ago.

Sorry phil and princec, my bad. Didn’t mean to insult you or anything (I read it over and it does kind of sound dumb, sorry :/). I hope you understand my general point though, but I guess if it doesn’t apply to you it doesn’t matter much. (I kind of took your mention of age and jumped off a cliff with it I guess haha)

I concede that’s a disadvantage.

Cas :slight_smile:

Yeah, “ingrained” is not perhaps the right way to describe how us old-timers operate. Over the decades we’ve found that some things work a lot better than others.

Cas :slight_smile:

Deservedly cautious maybe?

Standard Operating Procedure, for me:

  1. try various approaches
  2. pick best
  3. test choice occasionally against variants, go back to 2.

No, but it does matter though.

What sucked? Reading other people’s code or reading shit code (or both)? Anyway the topic is a new language here.

And before jumping on the conclusion that inferred types makes the language less readable, I’d strongly suggest you to try to use the language first (for something more than an hello program) and draw your own conclusion.

Because judging a language without even trying it’s really pointless.

Many people are already using it in production, is always one of the most loved in the charts. I don’t want you to trust us when we tell kotlin is great or the other when they say is bad, but I’d like you to just give it a try.

Wouldn’t be some of your time worth trying something that you may potentially like and use?

His (and my) points are usually about better code in general - I think it’s clear that we’re not talking about “less syntax”. Less syntax is preferable if the intent remains clear and the readbility is enhanced. I won’t say less syntax is a general solution. In fact, I tend to say the opposite most times. In this discussion we talked about possibilities to enhance readability by leaving out information that is not needed (yea, I got it, if I use a text editor than it is needed). Hilarious is his example (see below), not his opinion about val/var - although it should be clear that I have no sympathy for argumentation that starts with “but when I open it in my text editor”.

His counter example … I really try to find nice words for this. It was basically a suggestion to add better syntax for an implicit (always) unsafe (it circumvents compile time safety) cast. Two possibilities: Either I am missing a big thing here (and I am open for a hint here), or we are talking about something that every Java programming noob knows should be prevented at all costs.

The baseline here is, that you really can’t have a discussion about language features and code readability, is these are the foundations…

Dynamic typing and type inference should never ever be said in the same sentence. It should never ever be confused - languages like JS having var vor variable type…with type inference you have a variable and a value. Two completely distinct concepts. With type inference you have the convenience (what people like about dynamic languages) and the safety (what people like about static languages) from both worlds. The “tiny bit” you mentioned is the key. The truth is: The types aren’t gone. But they don’t bother you any more in some situations. As without type inference, there is and will be no need to keep types in the head etc.

I hope it’s clear by now that we’re not talking about dynamic typing (and I personally hate dynamic typing, believe me). The thing is: You can understand type inference as the distraction free mode… as I explained before, you most often don’t need to know the exact type, it’s sufficient if the type is there. But you think you want to know, if you never really used the system, like elect just says it. And that makes this discussion so painful for everyone. Look, the exact same discussion was done when C# introduced the feature ten years ago. And scala has it. And swift has it. And Ceylon has it. And pretty much everytime it was the same: The conservative people with no experience with this feature say “no you can’t do it” and everyone else is totally satisfied with it. Can’t say more about it.

I’ve got pretty extensive experience of type inference through lambdas which I’ve been using happily since they were available in EA. Although it’s made the code a bit less busy on-screen it has caused numerous issues:

  1. The IDE can get awfully confused and it seems to break all sorts of little things in the editor until you’ve fully formed your lambda expression…
  2. …a task made harder because the IDE can no longer figure out how to do it for you, rendering it little better than Textpad, and you suddenly realise just how dependent you are on the IDE doing 1000 little things to make editing code easier when it stops doing it.
  3. When looking at code written some time back it is frequently completely opaque to you as to what the types of the arguments are in the lambda. Much is just hidden away as if it’s not important to understanding what it is doing… but it is. Very important. You often have no direct idea even what interface the lambda was implementing if there is potential for similar looking possibilities.
  4. You can get around most of that by … declaring the types of all the arguments. Duh :slight_smile:

However… as I said earlier, lambdas save so much cluttering boilerplate that these disadvantages are generally outweighed by the advantages by a pretty substantial margin of win. The type inference has been improved in Java 9 too, so all’s good.

Regarding the type inference in the automatic cast: as I say, I concede that it theoretically opens the possibility of any assignment throwing CCE instead of just ones you were explicit in acknowledging with a cast. But if you came at it from a totally fresh viewpoint that trained you to understand that all assignments can throw CCE from the get-go, you would simply accept it as the way things were. Things would be different if CCE was a checked exception - but it is not. It is a runtime exception. You can in theory apply the same argument to array indexing: any array index can in theory be an IOOBE, but for some reason this doesn’t bother you. That’s because it’s always been that way, and it’s a runtime exception, not a checked exception.

Cas :slight_smile:

Btw regarding point 3 above: I have found that the quickest and easiest way out of this hole is, depressingly, to use Eclipse to refactor the lambda back into an anonymous implementation! Thus telling me what interface it was, what the arguments were, and even allowing me to easily go look at the Javadoc for it. Kinda ridiculous really that this is the quickest way of understanding what the hell it is in front of you at a glance. (Then I refactor it back into a lambda. Fortunately Eclipse makes this easy… but I often don’t have source code in Eclipse when I’m trying to decipher it).

Cas :slight_smile:

Hmm… how do I refactor all my anonymous inner classes to lambda automatically in eclipse? Couldn’t find it yet :confused:

@topic
Well, personally I have no experience with Kotlin, but I like its smart casts:


MyClass a = ...;
if(a is SubClassOfMyClass)
   a.useSubClassMethod();

is in Java


MyClass a = ...;
if(a is SubClassOfMyClass)
   ((SubClassOfMyClass)a).useSubClassMethod();

or with further usage


MyClass a = ...;
if(a is SubClassOfMyClass) {
   SubClassOfMyClass castedA = (SubClassOfMyClass)a;
   castedA.useSubClassMethod();
   castedA.useAnotherSubClassMethod();
}

This is just a small visual thing, I would really like that for Java with instanceof operator :slight_smile:

Okay I got it. There is simply no way of rescuing you from the last 30 years of your life and I won’t further try it. The fact that you are mixing type inference with lambdas and local variable type inference alone and that you have problems reading and/or understanding Java’s functional interfaces usage is enough, although you are such an experienced developer. As mentioned too many times again, there are situations where some concepts are not appropriate. For example it should be clear that using lambda stuff everywhere could be a sign of bad code - just as anonymous classes can make code totally unreadable, where lambdas are appropriate.

Besides is mentioned (to have something for the original topic again), that in Kotlin you have proper function types, so no interfaces involved (directly) here.

I can also discuse all that but: there is no big difference in language and code itself
if its return same result and pass all Tests on it.
if code crushes in runtime then its Test error and not code itself

up:
There is a difference between:
Test on Refactoring
and
Test on function (class, module) result and entering params)

p.s Writing “result” Test is hard

  • (TD) (“4” “3” “12”)("-4" “3” “-12”)(“4” “-3” “-12”)("-4" “-3” “12”)
    (“0” “3” “0”) (“4” “0” “0”)(“0” “-3” “0”)("-4" “0” “0”)(“0” “0” “0”)

– because on practice you fully write again tested function(TF) that produce same result without optimizations


int Mul(int v1, int v2){
	if(v1 == 0 || v2 == 0){
		return 0;
	}
	int sum = 0;
	int v2_A = v2;
	if(v2 < 0) v2_A = -v2;
	for(int i = 0; i < v2_A; i++){
		sum += v1;
	}
	if(v2 < 0) sum = -sum;
	return sum;
}

-And about TIF(TE) – I not so smart to even write test data for it XD


-& < v1 < &
-& < v2 < &
v1 == 0 {0}
v2 == 0 {0}
r=0 0..(A(v2))[r += A(v1)]{r.s = v1.s * v2.s}

(I can’t even call it properly ^^)

up2: OK i finally write test for TIF with explanations)


v1 == 0 r
v2 == 0 r
v2 > 0 r
v2 < 0 r

test case


-+v1 -+v2

generate


if(v1 == 0){
	return x;
}
if(v2 == 0){
	return x;
}
if(v2 > 0){
	return x;
}
if(v2 < 0){
	return x;
}
//Eroor can't go here

filled Data
produce same result on any val enter if no extra val present that not final(const)


if(v1 == 0){
	return 0;
}
if(v2 == 0){
	return 0;
}
if(v2 > 0){
   int sum = 0;
   for(int i = 0; i < v2; i++){
      sum += v1;
   }
   return sum;
}
if(v2 < 0){
   int v2_A = -v2;
   int sum = 0;
   for(int i = 0; i < v2_A; i++){
      sum += v1;
   }
   sum = -sum;
   return sum;
}

test data
(“4” “3” “12”)("-4" “3” “-12”)(“4” “-3” “-12”)("-4" “-3” “12”)
//
(“5” “3” “11”)


if(v2 > 0){
   int sum = 0;
   for(int i = 0; i < v2; i++){
      sum += v1;
   }
   if(v1 == 5){//no situation like this - because can't add "if" manually
      return 11;
   }
   return sum;
}

final const external var


final static int C = 1
...
if(v2 > 0){
   int sum = 0;
   for(int i = 0; i < v2; i++){
      sum += v1;
   }
   sum += C;
   return sum;
}

(“4” “3” “13”)
(“5” “3” “16”)

-One Test Data covering all situation no mater in what range params are
(except Cpu register overflow ^^)