HNHacker News
TopNewBestAskShowJobs

kbp

807 karma · joined October 19, 2016

submissionscomments
kbp··on Absolute truths I unlearned as junior developer
The "who wrote this?" mentality is a trap that's good to avoid. Get comfortable with different ways of writing something that, while they might have different tradeoffs, accomplish the same thing, and try to see past that. Understand that most code wasn't written by anybody--lines 1 and 3 were written by Alice a year ago, line 2 was written by Bob 2 years ago, and line 4 was written by Alice yesterday. `git blame` is very useful for seeing the change in context, which can give a lot of insight into why it's written that way, but usually the author isn't very useful to know, unless you're planning to ask them about it. Sometimes it's useful if you happen to know that the author isn't very familiar with something when you're wondering why they didn't use it, but try to keep in mind what the actual benefits of your way are, whether they're especially pressing, and that the other person might have written it differently because they were thinking about other concerns that you forgot.
kbp··on TypeScript 3.5
What features are you thinking of in those languages? I don't know Swift but I can't think of anything comparable in OCaml.
kbp··on The Art of Command Line (2015)
In Emacs, every key is evaluating some Lisp expression. You are interactively using Emacs Lisp in a funny sort of REPL. Most of the time you just use predefined commands and they do what you want, but if you know there's a whole programming language there, then you'll see opportunities to take advantage of that sometimes, just like how sometimes it's nice to be able to write a for loop or a pipeline at a bash prompt.

Once you get used to that model of using a computer, it feels crippling to use applications that you can't easily program in on the fly. It's the difference between having a full programming language and a bunch of buttons you can press, and it's for something you're going to be doing a lot for a long time.

kbp··on Why OO Sucks by Joe Armstrong (2000)
I think we're coming at it from different angles. My point is that there shouldn't be any abstraction to write, and it should just be the way the language works. Primitive slot access in Java is not just a get/set interface, it's a get/set interface that also specifies implementation characteristics and what the code will be capable of in the future. It should be in the language so that you can have primitive slots, but it shouldn't be part of the interface you expose for your own modules, because adding pointless coupling to your code does nothing but restrict future changes. Languages should not provide an easy shortcut for writing interfaces like that.

I don't view it as a useless abstraction, because I view it as the natural way of things. I view specifying that your get/set implementation is and always will be implemented as slot access to be uselessly sharing implementation details that does nothing but freeze your current implementation strategy.

I think a better question is when that abstraction gets in your way. When does it bother you that nullary functions aren't reading memory locations? Why do you feel that's an essential thing to specify in your public interface, as a default? There's nothing stopping you from writing code in Python and mentally modelling o.x as slot access, because it follows the interface you want from it.

If you only care because it's something extra you have to do, then that's what I meant by boilerplate. I think it's a misfeature of Java's that it presents a model where that's something extra you have to do.

kbp··on Why OO Sucks by Joe Armstrong (2000)
Maybe instead of "restrict" it would be better to say "be cognizant of." If you want to expose a get/set interface, that's fine, but doing it with a public property in Java additionally says "and it's stored in this slot, and it always will be, and it will never do anything else, ever." I don't see what value that gives in making easy changes for anyone. I don't see why that additional declaration should be the default in a language.

You get into the same issue with eg making your interface be that you return an array, instead of a higher-level sequence abstraction like "something that responds to #each". By keeping a minimal interface that clearly expresses your intent, you can easily hook into modules specialised on providing functionality around that intent, and get power and flexibility right now in a way that doesn't hamstring you later. Other code can use that broad interface with your minimal implementation. Think about what you actually mean by the code you write, and try to be aware when you write code that says more than that.

I think it's interesting that you associate that interface-conscious viewpoint with bondage and discipline languages. I mostly think of it in terms of Lisp and Python and languages like that where interfaces are mostly conceptual and access control is mostly conventional. If anything, I think stricter type systems let you be more lax with exposing implementations. In a highly dynamic language, you don't have that guard rail protecting you from changing implementations falling out of sync with interfaces they used to provide, so writing good interfaces and being aware of what implementation details you're exposing becomes even more crucial to writing maintainable code, even if you don't have clients you care about breaking.

Of course all this stuff goes out the window if you're planning to ditch the codebase in a week.

kbp··on Why OO Sucks by Joe Armstrong (2000)
You're always using a getter. It's just a question of what syntax your language provides for different ways of getting values, and how much they say about your implementation.

Most people don't have a problem with getters and setters, they have a problem with writing pure boilerplate by hand. Languages like Python and Lisp save you from the boilerplate and don't provide a nicer syntax for the implementation-exposing way, so people don't generally complain about getters and setters in those languages, only in Java and C++ and things.

kbp··on Why OO Sucks by Joe Armstrong (2000)
The important thing is restricting your public interface, hiding implementation details, and thinking about how easy your code (and code that uses it) will be to change later. It's not an OO vs anything thing.

When you want a value from a module/object/function/whatever, whether or not it's fetched from a location in memory is an implementation detail. Java and co provide a short syntax for exposing that implementation detail. Python doesn't: o.x does not necessarily mean accessing an x slot, and you aren't locking yourself into any implementation by exposing that interface as the way to get that value. It's more complicated than Java or whatever, here, but it hides that complexity behind a nice syntax that encourages you to do the right thing.

Some languages provide short syntax for something you shouldn't do and make you write things by hand that could be easily generated in the common case. Reducing coupling is still a good idea.

kbp··on Withdrawing from the Microsoft MVP Program
I don't know a lot about the programme, but I would have assumed there was always a similar focus on Microsoft's interests. Did they used to support people who weren't very interested in new/trendy/popular MS technologies?
kbp··on I Miss Rails
> MVC is a 20 year old pattern

More like 40; it's from late 70s Smalltalk.

kbp··on Why I Switched from Python to Clojure (2016)
> Not sure what this means. The only support I need in an editor is the ability to use tab and shift tab on blocks of text to change the indentation level. It's visually obvious when code is correctly indented.

In Emacs you can use C-M-f and C-M-b to move back and forth over / select paren/bracket/brace delimited blocks, or in vi you can use %, both with 0 configuration in a language-unaware state. If you're editing C or Lisp or whatever, these generic commands are useful. Editors don't tend to have move-to-next-less-indented-line (and similar) commands outside of Python modes or similar, in my experience, and even if they did, they'd need a bit more work than that to work properly because of indenting subexpressions.

kbp··on The Functional Style (2018)
> Yet you can absolutely write: > String str = "hello,"; > str += "world!"; So it's "immutable" for some lawyerish definition which does me no good.

`str` is a mutable reference to an immutable object. You can make the reference point to something else, but the object being pointed to is immutable, so eg if you pass it to a function, that function cannot change it under you. If you want to make the reference immutable, declare it as final. I don't think understanding the difference between a pointer and the value it points to is lawyerish.

kbp··on “No, we’re telling everyone we are using Java”
> Recursion is the way to go in Erlang / Elixir

I think it's important to realise that they're different ways of writing the same thing. For example, in Lisp, the 'do' operator is basically a C-style for loop: in Scheme, it's a macro over tail recursion, and in Common Lisp, it's a macro over gotos, but it provides an almost identical interface to programmers. Using recursion over loops is just a stylistic/syntactic choice, the really important part is understanding how recursive functions are equivalent to loops, and vice versa, so that you can apply your experience in one situation to the other.

kbp··on “No, we’re telling everyone we are using Java”
> No loops? That can be life changing.

I doubt it would be for someone from a Ruby background, where higher order functions already generally replace built-in loops.

kbp··on Introduction to Theoretical Computer Science
It's not a wiki; he's free to not merge changes people offer him.
kbp··on A Book about Qt5
LispWorks CAPI is very good. It's a shame it's proprietary and not cheap.
kbp··on The hard part in becoming a command line wizard
But Unix didn't adopt everything-is-colon-separated-values. Everything being unstructured text leads to a lot of different, incompatible ways of structuring that text. S-expressions themselves aren't important, I think, it's just having some standard structure that's used everywhere and you don't have to parse yourself. Trees are a good choice for a universal structure, hence things like XML. S-expressions are just a very lightweight and flexible format.
kbp··on Ask HN: How to be productive with big existing code base
I haven't read it, but the second edition of that book used Javascript for the examples.
kbp··on Why Pascal Is Not My Favorite Programming Language (1981)
I was just saying that there's no good reason to have different variables with names that only differ by case; the example you gave where you do like that has a better solution in multiple namespaces.
kbp··on Why Pascal Is Not My Favorite Programming Language (1981)
> In fact I often use the "Thing thing" approach to variable declaration and I think I like it. It's an easy way for me to avoid thinking about taxonomy. But it's not that important. If it wasn't possible I could invent different names.

There's no reason that types and variables need to live in the same namespace. The language can know what it's expecting at a certain point. Putting them in different namespaces, like Lisp does, lets you re-use the same name for types and variables even with matching case, and is more waterproof with regards to clashes than a case convention.

> There simply isn't any good reason not to always use the same case for any variable throughout a project.

I agree, but I also feel that there isn't any good reason to have multiple distinct objects in the same namespace whose names differ only by case. It just seems like a recipe for confusion.

When I'm quickly iterating on something, it's nice being able to be lazy and inconsistent with capitalisation. Standardising that in a codebase is important, but it's more of a job for a linter, I think.

kbp··on Why Pascal Is Not My Favorite Programming Language (1981)
> Another thing that's driving me crazy is case insensitivity. I would never willfully choose a language with case insensitive identifiers. It's driving me nuts.

What about it annoys you? Do you often define a lot of variables whose names differ only by case, in languages that let you? Common Lisp normally behaves as though it were case insensitive, and I've never found that to be a pain point.

kbp··on Why Julia
Smalltalk doesn't have them, either.
kbp··on A Newly-Generated Create-React-App 2.1.5 App Has 1,568 Dependencies
> Yes but good luck with React.createElement(). React without JSX is really a pain to use (or Preact, Inferno, etc).

What's painful about it? I prefer it without JSX, personally; JSX is a pretty simple syntax transform that doesn't really gain you anything that I can see, makes manipulating props a lot clumsier, and needs extra tooling. Most of the time it's almost identical with or without JSX, but when there is a difference, I've always found without to be smoother and clearer. You definitely want to assign React.createElement a shorter name, though.

kbp··on Harder programming questions do a worse job of predicting outcomes
I think those "easy" examples are too easy to get any meaningful signal from. If they struggle, they have no idea what they're doing, and if they don't, you don't really learn anything about how they work because there's not much to them.

Other people have mentioned Triplebyte using console tic tac toe as a question; that seems like a better sort of "easy" question that still lets the interviewee have a chance to show off their problem solving and factoring skills.

kbp··on German for Programmers
Duolingo has notes explaining the grammar as it introduces it, for the most part, and the grammar gets reasonably sophisticated by the end. Not really what I'd call complex nuances, but probably equivalent to a year or two of university study. What second-week German grammar concepts do you think it doesn't brush on?
kbp··on Lombok makes Java cool again
> When design patterns came along, Java folks talked about them as though they were a wonderful new invention. But they only exist because Java is so clumsy that it needed crutches to do things that had been easy and natural in other languages for years; someone merely came along and gave the crutches names.

Design patterns are a useful way of thinking about any sort of design, not even just in programming. Novels and paintings have them, too, so does your favourite language. There will always emerge from experience particular ways of using your medium, and having names for those patterns can actually be pretty useful for thinking about them and structuring them into a good design (like how SICP talks about knowing a spirit's name gives you power over it). You can't avoid using design patterns; someone just might not have come along and named them yet, or you might not be aware of them.

The GoF book itself actually discusses this in the first chapter a bit, here's a relevant part:

Point of view affects one's interpretation of what is and isn't a pattern. One person's pattern can be another person's primitive building block. For this book we have concentrated on patterns at a certain level of abstraction. [...] Our patterns assume Smalltalk/C++-level language features, and that choice determines what can and cannot be implemented easily. If we assumed procedural languages, we might have included design patterns called "Inheritance," "Encapsulation," and "Polymorphism." Similarly, some of our patterns are supported directly by the less common object-oriented languages. CLOS has multi-methods, for example, which lessen the need for a pattern such as Visitor.

kbp··on Comparing Rust and JavaScript Ergonomics with a Simple Linked List
> Complicated pointer-type data structures like linked lists

If a singly linked list is a complicated data structure then what's a simple one?

kbp··on How innovative is Clojure as a Lisp dialect from Lisp expert's perspective?
It's too early to say. Clojure's still very young in Lisp terms, so it's natural that it has more hype around it now than languages that were cool 30 years ago. It's also not exactly taking over the world, and I think you're forgetting the buzz Lisp had in the 80s. It will be an innovation in the sense you mean if it has wide adoption and hype in 2050, but it's certainly not anything unprecedented yet.
kbp··on Coconut: Pythonic functional programming
What do you mean by the last paragraph? foldl in Haskell is just

    foldl _ acc []     = acc
    foldl f acc (x:xs) = foldl f (f acc x) xs
And in Python something like

    def foldl(f, acc, l):
        for x in l:
            acc = f(acc, x)
        return acc
Which doesn't seem much harder to read or write than any other version, to me (it's all just syntax around the same algorithm).
kbp··on A little-known C feature: Static array indices in parameter declarations (2013)
The standard says "If the expression is a constant expression, it shall have a value greater than zero." Clang gives me a warning that "static 0" has no effect. NULL is valid as a pointer to a 0-length array, so that makes sense that it wouldn't function as a non-NULL assertion.
kbp··on Why MIT uses Python instead of Scheme for its undergraduate CS program (2009)
I agree that there's a problem of people (even the people who rave about how enlightening it is) misunderstanding that a toy Scheme interpreter is what Lisp is, but I don't think that's an issue with Scheme. Introductory FP classes that use Common Lisp don't leave any better a taste in students' mouths, and real world Scheme is a lot more capable than a toy implementation designed for pedagogical purposes. I don't think the standard's conservatism is very much a factor.
← PreviousPage 2 of 12Next →