Hacker News new | past | comments | ask | show | jobs | submit | mishoo's comments login

This isn't an Arch problem, it's a Gnome problem. Extensions break all the time because in order to do anything non-trivial they must use "undocumented" APIs (well, there's no documentation anyway, just a hello world tutorial and then may the source be with you). I know it because I wrote my own extension [1] in order to make this desktop bearable.

After a while, though, I switched to KDE and life's good again.

[1] https://github.com/mishoo/boring-gnome-mishoo.github.com


Now add a Common Lisp compiler to it and you reinvented technology from the 80'es. :-)


If you want to get pedantic then clear text consoles are the core concept behind time sharing systems, the methodology behind Multics and UNIX, and thus pre-dates LISP Machines by decades (we all stand on the shoulders of giants).

But that doesn't mean there isn't still value in someone writing a new library and sharing it with the community.


Interactive LISP consoles were used before UNIX or Multics existed.


Indeed however to be analogous with the submission those consoles would still need to be running on a time sharing system like I described.

Time sharing systems also pre-date UNIX and Multics, which is why I exampled them as being operating systems that use the time sharing metaphor.


Right, Time sharing wasn't implemented yet at that time, when Lisp was having its first interactive console in 1960. It was then also implemented on the first time sharing operating systems.


ok, let's put it another way, a LISP console is all well and good but systems in 1960 weren't yet multi-tasking (or at least multi-tasking systems in 1960 were still rare) so you couldn't have a LISP process running as one thread and query it's running state from another.

The reason I keep hammering on about time sharing is because they largely came hand in hand, time sharing systems needed to support multi-tasking whereas single user systems didn't (you still see echoes of this in the 80s with CP/M, DOS and 8-bit micros running BASIC). In fact if you look at the history of multi-tasking it roughly follows the same time line and lineage as the uptake of time sharing systems (around mid '60s IIRC). Before then you'd have to stop the execution of one program before you could start execution on another.

I know some "LISPians" like to think everything in computing eventually leads back to LISP but that's not always the case (and I say that as a big fan of the language myself).


One might just write a main loop, which takes Lisp expressions (or other input) from two or more different terminals and executes each expression interleaved. Those were not 'concurrent programs' which shared some state, but function calls within the same Lisp system, using an interactive execution loop serving several I/O devices. An early (mid 60s) application domain would be multi-player games over terminals controlled from a single process.

Lisp also has the idea of break loops, which halt the current execution (for example triggered by some kind of interrupt), allow interaction with the program state and then let one continue the program in some way. Thus one would not need to attach a debugger I/O loop from another process, but the debugger repl would be a part of the running program and could be called on demand.

That you 'know some "LISPians" like to think everything in computing eventually leads back to LISP but that's not always the case' doesn't invalidate the fact that Lisp systems were running on many of the early computers & operating systems from 1960 onwards and followed their evolution. Thus at least some interesting stuff has been done very early in Lisp, too.


> One might just write a main loop, which takes Lisp expressions (or other input) from two or more different terminals and executes each expression interleaved.

Pre-time sharing systems weren't multi-terminal. Hence why I keep coming back to time sharing.

Also your main loop example could be done in assembly, FORTRAN, BASIC, Pascal and C, two of which also pre-date LISP. There's nothing uniquely LISP about writing a polling loop.

Job control et al and multi-terminal mainframes are something very much born out of time sharing. You could use LISP to write your application that would run atop of that time sharing system if you wanted but you could also write that same application in a bunch of other languages too (assuming you had a compiler for that machine). And bare in mind around this time you could still physically inspect the state of paused program on a fair amount of single process systems (and those you couldn't would often punch out verbose log of its running state to tape).

> An early (mid 60s) application domain

By the mid 60s you had time sharing systems. Your argument was that LISP was doing this before then.

> That you 'know some "LISPians" like to think everything in computing eventually leads back to LISP but that's not always the case' doesn't invalidate the fact that Lisp systems were running on many of the early computers & operating systems from 1960 onwards and followed their evolution. Thus at least some interesting stuff has been done very early in Lisp, too.

I completely agree but you're attributing credit to LISP for something that isn't a language-specific feature. At least the OP was referencing a computing platform.

Anyway, this whole conversation was ridiculous from the outset and a massive distraction to the submission that sparked it. It doesn't really matter what came first; the only reason I even commented was to illustrate that we're all standing on the shoulders of giants so it's pointless mocking a submission for being similar in design to tech that pre-dates it. It's ironic that post lead to an argument about what came first.


> main loop example could be done in assembly

'Could' is the word. My example was that it was actually done to have built-in command loops and the building blocks for those (so that they could be used in programs), which could be invoked on demand while a program was running.

> it's pointless mocking a submission for being similar in design

I'm not mocking the submission. The feature is quite valuable and interacting with running software via command loops is great.


> 'Could' is the word.

Ok, "was" then. Operating systems were originally written in assembly and you can't write an operating system without some kind of hardware polling and command loops (even in the days before multi-tasking systems).

Even earlier computers in the days before operating systems would have command loops written in giant rings of punched sheets that would slowly spin round on reels like a cambelt. So this isn't even an innovation that was born from assembly, let alone any high level language.

I honestly do get what you're saying and I'm not trying to dismiss your point that people did this kind of stuff in LISP but what you need to understand is that people did this in a great number of different ways, in different languages and even mechanically too.


You won't get what true "liveness" is until you work in Lisp or Smalltalk. The ability to change a function in a running program, without restarting it. Automatic reload might seem cool, but reload means your application restarts and loses state. Imagine you have some Web app and you open some menus/dialogs, perhaps it's connected to some server via WebSockets etc. and you find a bug somewhere, you go to the code to fix it, but reloading the page means you start from scratch and need to open again those menus/dialogs, and reconnect the sockets, in order to test your fix.

Common Lisp had true liveness for decades; it's almost mandated by the standard, it's designed in such a way that you can actually recompile a function, or even redefine objects, adding or removing properties or methods, at fucking runtime without restarting the application. Objects already instantiated will remain so and will be updated to reflect the change. You don't restart. That's the true "liveness", but seriously you don't get it until you try it, and once you get it you become depressed because you realize it doesn't really exist in any mainstream language.

JavaScript is some decades behind this dream, even with stuff like Webpack.


> You won't get what true "liveness" is until you work in Lisp or Smalltalk. The ability to change a function in a running program, without restarting it

This can be done in a number of other common languages today such as Java (JVM languages) and C# (probably all .NET languages). Most IDEs I've seen for those platforms support it.

Substantial enough changes to the code can require an application restart, but most changes you might make like changing the implementation of a function, adding new functions to a class, etc., will not. Hot Code Replacement (HCR) has been supported since Java 1.4: https://wiki.eclipse.org/FAQ_What_is_hot_code_replace%3F

Fully dynamic languages like Lisp and Smalltalk permit a greater degree of this than statically typed languages do, however, since they don't have types and a type system to wrangle with. When I've used it, hot code replacement supported most of the changes that conceptually make sense to support.


You'd be surprised to find out that Common Lisp has actually quite a strong type system (not Haskell-level but much better than C++/Java); just that it's optional. You get the best of both worlds — fast prototyping, and then when you decide upon the types, you can add type declarations, which usually result in (much!) faster code and robustness.


If you use webpack's hot reloading properly with something like React, then you get to keep your state - it's only the functions that get swapped out. So it's actually exactly what you describe, and it's brilliant - so much more productive. This isn't even all that new (in web dev terms) - I had this working probably four or five years ago now on a project.


Huh?

I do procedural music in JS/web audio, and my projects are set up so that changes to the logic and instruments all happen live, while the music continues to play.

How is that different from what you're describing? What specifically can't webpack/HMR do?


What tools do you use? Just web audio api? Or a higher level library?


I first started out using Tone.js (and recommend it!), but later wound up rolling my own engine and so forth. So I'm just using WebAudio directly (or via libraries I wrote).


It’s relatively simple to have live reloading of individual JavaScript modules in Webpack. If you change the text on a React button component, that module will be recompiled and its new version injected into your browser and re-rendered. The text on the button in your browser will change, but other state will not change (e.g. something in your Redux store).

I’m not an expert, but I think the way it works is that Webpack provides a way for JS modules to register callbacks for what should happen when Webpack detects changes in them and recompiles them. React then provides such a callback implementation for component modules that causes the individual component to re-render. Webpack’s development server also provides a way to inject new code into your app running in a browser.

Things get a little more complicated if you want to hot reload things that deal intimately with state, like Redux reducers or middleware. AFAIK people usually just have the browser do a full page reload when changes are detected in those modules. I think Webpack will actually automatically trigger a full page reload if it detects a change in a module which does not explicitly declare how hot module reloading should be handled.

I only mention React and Redux because it’s the only major stack I’m at all familiar with; I don’t know if other stacks provide similar functionality.


FWIW hot reloading React/Vue components come quite close to this.


So does ClojureScript and Figwheel.


> You won't get what true "liveness" is until you work in Lisp or Smalltalk. The ability to change a function in a running program, without restarting it.

Erlang provides this as well, as do many dynamic languages. However, aside from certain Lisps and Smalltalk that are image based, and a few others, liveness and source persistence are typically traded off for each other. I can make a live change to a Ruby system if it is set up to provide a REPL, but unlike a live Smalltalk change I won't then have the source code for the changed but available the same way it is for the rest of the system. As a result, in many languages live coding features are mostly a tool for experimentation (usually in nonproduction environment!) on code that will eventually be incorporated into traditional source tree for a from-scratch build.


- IBM's visual age for java provided most of this for Java too. (yes, it was modeled to the smalltalk env with the same name)

- Zope (python app server) had a feature where you could debug a web application (in production) in a private session, so all code modifications you did in your session were private until you committed the code.


- Jrebel is a commercial tool that also lets you replace bytecode in a running program without loss of state.


"Hot code replacement" is a Java VM feature. What makes JRebel useful is support for live reconfiguration of a gazillion Java frameworks (e.g. Hibernate, CDI, Spring etc) so you don't have to restart your server after changing some configuration annotations. It's expensive though and slows down startup so it's a tradeoff.


Nicely done, but Courier is the ugliest font on Earth (I don't have Monaco). For the sake of humanity, never write "Courier" in a CSS file. ;-)


Yes, I really don't understand that design choice. On Linux you have Deja Vu Sans Mono (same origin as Menlo which replaced Monaco 10 years ago) and on Windows Consolas is a pretty good default. Or because the website is for developers, just keep 'monospace' as the default.


Emacs, the One True Program.


I do, when I know the types match. Also, I always use == to test if something is either null or undefined; cases where the distinction matters are extremely rare, and this looks too silly: typeof foo === "undefined" || foo === null.


It's not always 10:1, but it seems to be a good average. This happened to me numerous times — I sometimes start with a quick and dirty solution for my problem, then refine and refine until I'm happy with the result, the performance, the code looks beautiful and then I'm like “heck, it's only 100 lines and it took me a week”. In more pathologic cases, I've spent a week just thinking about it, and then I started writing code.

I'm programming for 20 years and I still can't provide good ETA-s for non-trivial problems.


> I still can't provide good ETA-s for non-trivial problems.

Well, that's why they are non-trivial problems. Don't be too hard on yourself ;)


Exactly; you can only provide a more accurate estimation if you know all the details and the exact implementation and how fast you can type, and even there you have to take at least a 30% margin either way.

You can only be 100% accurate when it's done. Here's a chart: https://cdn-images-1.medium.com/max/1600/1*hS2GObQarMYhamPeV.... Basically, the closer you are to done, the more accurate your estimation will be.


To go even further on that point - the chart itself seems overly optimistic. +-40% of estimate after product design? +-10% of estimate after design spec?! Countless number of times I have seen detailed design specs completely thrown out of whack by new engineering, process or business revelations/insights. Human thought is iterative - most people can imagine at most 80% of the future/product/design possibilities.


Yeah this sucked to read... 10 years into programming and I thought pretty soon I'd be able to figure this stuff out on the 1st or second go...


What's wrong with:

    return {
        labels: data.items.map(function(value){
            return {
                type: "label",
                value: value > 10 ? value : value * 100
            };
        })
    };
I hope your project does not get too popular.


Even cleaner with ES6.

return { labels: data.items.map(value => { type: "label", value: value > 10 ? value : value * 100 }) };


Magit must be why Git was invented.


+1, but I tried patiently to move the mouse over the X (close tab button) and clicked a few times... one minute later it closed and I got away without a hard reset.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: