5 ms·
I think the author is so enamored with Smalltalk that they no longer see how quirky and non intuitive the Smalltalk syntax is. Case in point: ourList := {
by hota_mazi 5y ago
I think the author is so enamored with Smalltalk that they no longer see how quirky and non intuitive the Smalltalk syntax is. Case in point:
ourList := { 1. 2. 3 }.
ourList collect: [:in | in + 1 ].
Here it is in Kotlin:
val list = listOf(1, 2, 3)
list.map { it + 1 }
No spurious colon, dots sprinkled a bit everywhere, mysterious ":in" or pipe bar, square brackets. Just a very naked syntax.
Next:
ourList select: [ :num | (num \\ 2) = 0 ] thenCollect: [:n | n + 2]
Kotlin:
list.filter { it % 2 == 0}.map { it + 2 }
The next example is an ever better illustration of why Smalltalk feels so antiquated and wasteful, and is not respecting the developer's time:
ourList chain
select: [ :num | (num \\ 2) = 0 ];
collect: [:n | n + 2];
collect: [:m | m + 2].
Why do I have to find names for all these closure parameters? And why use a different name every time (num, n, m).
Again, Kotlin shows how to do it right:
list.filter { it % 2 == 0}.map { it + 2 }.map { it + 3 }
- samatman 5y agoThere is absolutely nothing whatsoever intuitive about the C flavor of Algol syntax. Popularity is familiarity, not intuition. To my aesthetic taste the Kotlin looks hideous and the Smalltalk elegant and light; but then, I'm able to read them both.
- pjmlp 5y agoBeauty is on the eyes of the beholder.
- VaxWithSex 5y agoHow does `it` look with two parameters? for example when you have #pairsDo: ? a, b, c, d pairsDo: [:first :second | first append: second] > ab > bc > cd
- maybe_pablo 5y agoThis would be: listOf("a", "b", "c", "d") .chunked(2) .map { (first, second) -> first + second } Or simply: listOf("a", "b", "c", "d") .chunked(2) { it[0] + it[1] }
- VaxWithSex 5y agolist.filter { it % 2 == 0}.map { it + 2 } Does `list.filter { it % 2 == 0}` dynamically create a list or an iterator or what does it do?
- brabel 5y agoYou've got to be careful in Kotlin. if `list` is an actual `List`, `filter` and `map` will create intermediate lists. To avoid that you must use `list.asSequence().filter { .. }.map { .. }.toList()`.
- chess_buster 5y agoThen the code is not the same of what smalltalk does with #select:thenCollect: Smalltalk's Collection classes have a method #species which return what class to use as the new container.
- jillesvangurp 5y agoI like Kotlin as well. One of the nice things about that language is just the enormous amount of attention to detail when it comes to usability of the language. Kotlin's lambda syntax is actually similarly verbose. But they allow you to use a default argument called it. list.map { it+1 } is equivalent to list.map { oldValue -> oldValue+1 } Still readable and you can easily just rename the it variable in your IDE to save a bit on typing. There are many examples in the language where little time saving syntactic sugar just helps the programmer having to type a lot. Kotlin internal DSLs are really nice once you wrap your head around how to create them. That's a trick they picked up from the ruby community. However, I do also appreciate just how far ahead of its time Smalltalk was. I played a bit with it in the nineties while in university around the time Java was released and had no IDE whatsoever. Refactoring, which is a super power now granted to those using Java or Kotlin and in much smaller quantities to users of other languages was actually invented in the smalltalk community. They had IDEs with refactoring built in as early as the late nineties. They pioneered a lot of good stuff. Sadly, the tool chain was a bit weird to deal with because another of their innovations was storing the program code in a database rather than a lot of text files. That actually facilitated a lot of the stuff that you could do with smalltalk. That's something that never caught on but wasn't necessarily a bad idea. I think Visual Age had this briefly for Java and then got rid of that when it became eclipse. A notable smalltalk dialect called self also existed. Together with Javascript, that's one of the few object oriented and protype based languages around. I think that was something that emerged out of Xerox and Sun in the eighties. Sun did some amazing things around that time. Such a shame that they ended up being gobbled up and destroyed by Oracle. I think you could say that smalltalk is to object oriented programming what lisp and scheme are to functional programming. They are the purest realization of those paradigms but ultimately they have proven less popular than more practical languages that are maybe a bit less pure. Kotlin is a great example of a language that has enough of the OO and functional heritage to be useful for both. They definitely cut some corners here and there and there's plenty for a functional language purist to take offense at. But for day to day usage, it's a very nice language.
- VaxWithSex 5y agoThanks for this nice writeup :)
- VaxWithSex 5y agoHmm, I think you are artifically & willfully inflating the Smalltalk examples. list chain select: [:i | i \\ 2 = 0 ]; collect: [:i | i + 2]; collect: [:i | i + 3].
- renox 5y agoThis example create a block for the whole elements each time, I wonder if this is also the case in Lisp?
- mpweiher 5y agoAs far as I can tell, your only actual complaint is that Smalltalk 80 insists on you naming block parameters. Yep, that's not ideal, but it's also a single minor issue and trivial to fix, even in Smaltalk 80, because blocks are just objects. Certainly Kotlin's alternative here of special-casing closures with one parameter and randomly assigning the parameter name "it" seems no better, and arguably significantly worse. The "listOF()" function (is it a function? Or special syntax?) certainly looks a lot worse than actual literal syntax, though I'd agree that Smalltalk 80's literal syntax is not ideal. In Objective-S, you can still use your own block parameters, but any non-named parameters will be assigned numbered $ names. list ← #( 1,2,3 ). list collect:{ $1 + 1 }. Of course, simple maps don't really require the syntactic overhead of a closure, a Higher Order Message is much better suited: list collect + 1. Next example list select: { ($1 mod: 2) = 0 } | collect + 2. Keyword syntax allows "operator-like" named methods. ourList select: { ($1 mod: 2) = 0 } | collect + 2 | collect + 3.
- vvillena 5y agoIt can be said that Smalltalk syntax isn't standard across other languages. Ruby has some Smalltalk-flavored syntax (e.g. blocks, symbols), and there's Objective-C, which more or less copies Smalltalk message syntax. But in both these languages, those bits are just a part of a much bigger language. And the same applies to Kotlin: what's shown here is just a small part of the whole language. The beauty of Smalltalk is that these snippets show 90% of all the Smalltalk syntax. There's not much else, really! It might not look like a modern mainstream language, since all of them feature C-style syntax. But it's still worth a look: learning it can be done in a single afternoon, and you would realize all the things you haven't realized yet about how clever that small syntax set is.
- projektfu 5y agoIn Kotlin, does the “it” of a lambda hide a variable named “it” in the outer scope? Also, The compiler of a statically typed language can know that a lambda that takes one argument is passed to a function that calls it with one argument. This would be hard to guarantee in Smalltalk so you’d need a convention that finding an undeclared variable “it” in the block converts the block to a one-argument block. Finally, I imagine nullary lambdas in Kotlin are less common than no-argument blocks in Smalltalk.
- hota_mazi 5y ago> In Kotlin, does the “it” of a lambda hide a variable named “it” in the outer scope? Yes, which is why it's recommended to name your closure parameter (instead of using `it`) when you nest these.
- jrochkind1 5y agoI think Smalltalk seems "quirky" compared to your Kotlin example only becuase we've all gotten used to a standardized C-inspired syntax. Which is fine, we have, so things that roughly adhere to it seem less quirky. Smalltalk was just written before we had all standardized on that. There's nothing inherently more quirky about separating list elements with `.` then with `,`, until you've gotten used to a cross-language convention of using `,`. Which Smalltalk predates. There's nothing inherently more "naked" or less mysterious about using square brackets to delineate a block/lambda instead of curly brackets... and I'm not even sure on what basis curly braces seem more natural to you! What makes curly braces more obvious than square brackets? Why do you have to find names for closure arguments? I don't know why do you have to find names for arguments in functions/methods either? One could imagine a language (perhaps untyped, to keep things consistent) where you didn't, perhaps any one-argument function would just have an argument named `it`. Heck, maybe a two argument function would just have arguments named `it` and `other`. We could argue about whether that was a good idea or not... but I'm unpersuaded that it's more "naked", as if there is some kind of natural correct one true syntax out there waiting to be discovered. I get that you like Kotlin; I think you are mistaken to think it is objectively more "advanced", and am confident we could find people who don't like some of it's choices.
- Kinrany 5y ago> One could imagine a language It's called Kotlin. Of course this is a relatively minor feature and few C-like or ML-like languages have it. Using it against Smalltalk is a bit unfair.
- jrochkind1 5y agoOh kotlin automatically names arguments for all functions/methods, not just anonymous blocks? I'm obviously not familiar with kotlin. I'd call it "quirky" to suggest that it's more "advanced" to automatically name arguments `it` for all function definitions! I thought the kotlin enthusiasts were only suggesting it for anonymous inline blocks/closures, but was hypothesizing, ok so would doing it for all functions be even more "advanced"? (Is the answer that kotlin already thinks yes?!)
- igouy 5y ago> non intuitive It isn't "intuition". It's familiarity from using some other language that used {} syntax. > mysterious ":in" Less mysterious as list collect: [:each | each + 1 ]. or list collect: [:element | element + 1 ].