Hacker News new | past | comments | ask | show | jobs | submit login

What's your opinion on Julia given its Dylan heritage?



Julia is almost good enough for me to use, but not quite. I'd prefer an s-expression syntax, but that's not a deal killer for me. I like some other languages that don't have s-expression syntaxes, though I miss the easy text manipulation that s-expressions support.

I would want a convenient way to deliver a self-contained executable. If there's a simple way to do that with Julia, I don't know about it. I look for it periodically, but haven't found it. If it's there and I've simply overlooked it, then I might actually start using it regularly.

I have a few other nits, but they're just nits. On the whole, I think Julia's pretty nice.


One thing I forgot to mention is that I don't know whether Julia handles dynamic redefinitions gracefully.

What I mean is, for example, if I evaluate a new definition of an existing class, what happens to all the existing instances of that class? In Common Lisp, the old instances are now instances of the new class, and there is a runtime facility, defined in the language standard, for updating existing instances to ensure that they conform to the new definition.

If a language lacks facilities like that, then it's hard to work the way I prefer to work.

I guess I sort of expect that Julia will not have graceful support for redefinitions, because, generally speaking, the only people who even think of that feature are people who are intimately familiar with old-fashioned Lisp and Smalltalk systems, and they're sort of thin on the ground.

But maybe I'll be pleasantly surprised.


Julia doesn’t have classes. It relies on multi-methods primarily. Which for scientific computing is a much better fit, IMHO. That being said it’s possible to redefine pretty much any operator, including built in ones at the repl.


Your reply is a bit confusing, because multimethods are not an alternative to classes. Common Lisp and Dylan, for instance, offer both multimethods and classes.

Regardless, Julia does offer user-defined composite types. Can I redefine a composite type without halting the program in which it's being used? If so, what becomes of existing instances of the type?

If the answer to the first question is "yes," and if the answer to the second one is "the language runtime arranges for the existing instances to be updated to be instances of the redefined type," then Julia offers the kind of support for redefinition that I am accustomed to in Common Lisp. If not, then it doesn't.

EDIT: I dug around and answered my own question: Julia doesn't support redefining structs in the repl.

There's a project in progress (Tim Holy's Revise.jl) to add support for redefining functions in a session, and that project contains some discussion of how they might approach redefining structs.

Of course, the existence of the project and those comments implies that Julia does not currently support such redefinitions, and that answers my questions.

I did notice from the comments on some issues that those folks are aware that supporting redefinition of structs in the repl implies that existing instances may become orphans when their types are redefined, and there's some discussion of what to do about it. Common Lisp's solution--updating the existing instances to conform to the new definition--does not seem to have occurred to anyone.

That's not a big surprise. Why would such a feature occur to you unless you were consciously designing a system for building programs by modifying them as they run? Of course, that's exactly what old-fashioned Lisp and Smalltalk systems are designed for, but most people don't get much exposure to that style of programming.

I always end up missing those features when I don't have them, though, which is one reason I always end up going back to Common Lisp.


True, classes and multimethods aren’t exactly interchangeable. It’s just that I haven’t found classes useful (at least as done in Java/Python/C++ objects) as compared to the combination of multimethods and type specialization. At least in the context of scientific computing.

Does CL use virtual tables to implement CLOS? Always been curious about that. It seems CL must keep the state associated with redefined objects. How do you handle new fields and filling in values with CLOS?

It does appear you can’t redefine structs in the repl. Forgot about that point, though as you point out there doesn’t appear to be anything fundamental to prevent that from being changed in the future. I haven’t used Julia day-to-day much for a while, but hopefully the newer generation tools will add in the “old” features from CL and similar.

Have you ever tried CLASP?


CLOS classes are logically equivalent to structs. In fact, in some implementations, they are exactly the same. They are therefore useful in exactly the same ways and the same circumstances that structs are useful.

Maybe what you don't find useful is inheritance. I can see that. I'm not heavily invested in inheritance myself, though it can be useful in cases where you want a bunch of structs with some shared structure, or in cases where you want multimethods that share some behavior across a bunch of related types.

The terminology "virtual table" is commonly used with C++ and other languages that associate methods with classes. Each class in such languages has a hidden member that contains a pointer to a virtual method table used for method dispatch.

In CLOS, methods are associated with generic functions, not with classes, and are dispatched on any number of arguments. The standard specifies how generic functions and methods behave, but does not specify how they are to be represented, so the representation is an implementation-specific detail.

A naive toy representation might be a table associated with each generic function that maps sequences of types to methods. When the function is applied, Lisp computes the values and types of the arguments and finds the appropriate method for those types. I'm sure you can imagine the sorts of optimizations implementations apply to speed things up, including compiling monomorphic generic functions to simple function calls.

This is a bit of an oversimplification, because CLOS also provides a bunch of ways to control and customize how dispatch works--CLOS is less an object system than it is a system for building object systems.

When you redefine a class, CLOS automatically calls MAKE-INSTANCES-OBSOLETE, which arranges for all existing instances to be marked obsolete (it's up to the implementation to determine exactly what that means). When control touches an obsolete instance, the runtime calls UPDATE-INSTANCE-FOR-REDEFINED-CLASS with the instance, a list of added slots, a list of discarded slots, and a property list mapping the names of discarded slots to the values they had when they were discarded. If you've specialized UPDATE-INSTANCE-FOR-REDEFINED-CLASS for the case in question, the instance is reinitialized according to your specialized method, and things proceed as if it had the new type definition when it was instantiated.

If you haven't specialized UPDATE-INSTANCE-FOR-REDEFINED-CLASS then you'll end up in a breakloop. A breakloop is a repl session with read and write access to the call stack and the variable environment. The assumption is that you'll inspect the stack and environment, decide what UPDATE-INSTANCE-FOR-REDEFINED-CLASS needs to do, write that code, then invoke a restart that causes the halted function to resume execution as if your new definition had existed when it was originally called.

Again, the language is designed with the assumption that writing a program by modifying it while it runs is standard operating procedure. That being the case, the obvious thing to do when there isn't a relevant definition for UPDATE-INSTANCE-FOR-REDEFINED-CLASS is to offer you the chance to create one, and resume execution from there once you've created it.

I've examined CLASP a bunch of times. I keep meaning to mess with it, but I haven't yet.


>I would want a convenient way to deliver a self-contained executable.

It's a bit rough around the edges, but it does exist: https://github.com/JuliaLang/PackageCompiler.jl


Excellent; thank you! I'll take a look.




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

Search: