1: http://compcert.inria.fr/ is the only non-toy one I'm aware of to be formally proven.
If you demonstrate a bug in gcc or rustc (or one of their base libraries), it is a major issue that will at least get documentation and a warning (and likely a quick fix). In Julia, even documenting it may be relegated to the middle of the todo list.
Of course it's annoying that Julia itself is this buggy, but the problem is sometimes framed as if it causes some fundamental uncertainty and doubt about your program because the compiler can't possibly be debugged, whereas is my experience, when you see a Julia bug, it's just another bug, usually in some bog-standard stdlib function which you can easily inspect using code introspection.
And again, I've maybe seen 20 Julia bugs in 4 years of coding it daily, compared to probably 20,000 of my own bugs.
Efficient Julia code should normally look simple and elegant, not 'ugly' (unless you are going into deep optimizations, like manual simd, or some times heavy reliance on in-place operations.)
I think calling it 'deceptive' is problematic. Of course you can write slow code in Julia, like in any language, but did you write code that you think should be fast, but wasn't?
> I don't buy "it's compiling at run time" argument, since other (interpreted) languages do not have this problem.
I'm a bit confused by that statement. Compiled languages have to compile, interpreted don't. What did you mean here?
But we also have very rigorous testing infrastructure and a community that cares deeply about these things and moves very fast to fix them. You'll notice that every legitimate issue in that post is now closed and fixed, and the remaining ones are about the users misusing in place functions in the presence of aliasing.
* There are no interfaces
* Existing abstract types are mostly undocumented: It's unknowable and certainly untestable what constitutes an IO or a Number or even an AbstractArray (yes, even AbstractArray leaves important edgecases unspecified). I've written 100 methods that takes `::IO`, yet I don't actually know what it can take. Much of the issues with unsupported package interactions come down to this: One package doesn't know what it promises, and the other one doesn't know whether the promise is upheld. E.g. it's still unclear to me whether `OffsetArrays` actually fulfill the contract of an AbstractArray. If not, it's a bug that it's an AbstractArray. If so, Base is insufficiently tested, as it ought to test its AbstractArray code with an AbstractArray with offset axes.
* Base Julia have several functions that are simply not tested. CodeCov of Base is far from 100%
* Iterators are assumed by Base and Iterators to be immutable - a buggy assumption in many contexts
* It's not even clear what is public and private in a package. E.g. are fields of exported struct private? Where is that documented? And it's way too easy to rely on unexported symbols.
* Speaking of which, you can export stuff that does not exist.
* Projects does not have compat entries by default
* Generic functions are rarely tested generically - i.e. not with any minimal abstract type.
* Promotion rules of non-numbers are unclear and underspecified, and accidentally changed recently on master because it's not documented nor tested anywhere
* There is a lot of "Yeah, X isn't really semantically correct, but I can exploit its weird behaviour in my own code, so we shouldn't fix it, it's actually a feature" hacker attitude among Julians.
There are like, 100 more small things that make Julia more bug-prone. I think this is a serious issue about the language that we should take note of and try to work on. You'll notice several of these issues can be resolved. But we need to take it seriously.
I agree with this. Yuri's post requires a bit of Julia experience to understand the context of it, that much of it is about drop-in combinations of packages and types that one wouldn't even attempt in many other languages. Julia allows you to do that and makes it programmatically easy, which has significant benefits. But it also requires work on the implementers' side to get right.
> But we also have very rigorous testing infrastructure and a community that cares deeply about these things and moves very fast to fix them.
Not sure how much I agree with this. If you're talking about the language itself, sure. But a lot of the libraries don't have extensive testing infrastructures, especially not the kind Julia obviously needs based on the above, with beyond-the-expected-usecase tests. Maintanence of packages varies a lot, with the median being on the slower side. There's definitely "a community that cares deeply about these things", we just need more of it.
2. Can you elaborate more on "they are very awkward to work with and only offer a subset of the abilities of the Emacs plugin" for vim? What did you find lacking about either slimv or vlime that you absolutely couldn't stand such that you forced yourself to use emacs? I'm most familiar with slimv and am aware of some quirks (and one bad still-open issue related to errors in threads which is annoying to deal with when it bites) and some limitations, but I'm fortunate to be mostly unbothered by them or in one case so far submitting a patch to fix one annoyance. At least, I'm not bothered to the level of abandoning vim -- I'll probably try the VS Code plugin before trying emacs again, or shell out for a LW license. Specifically it's things I see emacs users do like clicking a printed object's memory address to open the thing in the inspector, or having a slightly less ghetto code stepper. I'd rather have other things I miss from my Java life that as far as I know aren't even in emacs for CL.
3. Did you seek out any downer takes when evaluating Julia? What did you think of any of them? Some specific examples include https://yuri.is/not-julia/ or http://danluu.com/julialang/ where Yuri's post is linked at the bottom as a sort of update. If you read anything like that, have you been concerned? Any good "excuse" articles you found that address any downer points?
Anyway, thanks for your work in Lisp Land, both in code and IRC messages.
2) The Vim plugins only support SLIME, not Sly, which offers many more features I simply can't live without, such as stickers. Additionally, indentation in Vim cannot be made dynamic. That is, for every macro you write, you are forced to edit a flat file that describes the proper indentation rules. I have a couple thousand lines of my Vim configuration dedicated to working in CL, and it still isn't good enough, compared to the experience in Emacs. And yes, there are countless bugs that don't exist in Emacs/Sly.
3) Yes, I read that post and some others. Bugs like the AbstractArray usage are programmer errors, nothing to do with the language. Julia is 1-indexed by default, but with libraries such as OffsetArrays.jl and CircularArrays.jl an AbstractArray can be indexed at 0. I shrugged most of this post off, because I don't see them as correctness bugs in the language proper. As for the TTFX (time to first plot/execution) as noted in the other article, that is a problem that is actively being worked on currently by Tim Holy, and it's not really an issue if you build your own image anyway, only when you are compiling the code each time you start up your fresh image.
I’m also curious to understand the reasoning, for either choice.
1. Editor support. The original poster bemoans that the only fully supported editor is emacs and that there is not sufficient support for neovim. I have used emacs and slime, but I had to stop because of the ulnar tunnel syndrome it was causing. But I knew vim before I learned emacs and I am a neovimmer myself. I have used jpalardy's plugin[1] for many years and couldn't be happier with it. There's a visible repl built in, so by definition it's fully featured. The reason emacs is the only editor for lispers is that it tries to be the whole operating system. It turns out using a terminal multiplexer along with an editor gives you everything you need. I like GNU screen on Linux and ConEmu on windows.
2. Community. The original poster speaks of toxicity and a community full of people who are not welcoming to newcomers who ask simple questions. I'm just barely starting my Common Lisp journey so I can't speak to that. But I don't know if I'm discouraged by a community that values members who are capable of doing their own research and not needing their hands held. I'm often surprised by developers who need YouTube videos to explain to them how to do their job as if they can't read their own code. Maybe that's why the documentation is so poor in the Common Lisp community: the expectation is that you can read their code and figure out what it does. The original poster says that the community is full of people who do not wish to work with others. That makes me feel like if I write in this language I'll be able to be productive even if no one else wants to work with me. I'm not hugely popular and don't have a ton of stars on my GitHub pages, so the idea of a language that allows me to be productive even if no one else wants to help sounds pretty good to me.
3. Packaging. The original poster speaks against packagers who take responsibility for the cleanliness of code before it gets packaged up for the quicklisp dist. He complains that packages are released on a monthly basis and that this is not fast enough for him. As a DevOps engineer, I think this is fantastic. I hate it when developers release code too frequently because the new releases often break things even when they are not intended to, and reacting to those changes takes time. A little bit of time before each release is easier on your consumers. I feel like the best sweet spot is 90 days. I'm getting killed at work right now because of the breakneck speed of helm chart packages and how fast they release completely breaking changes. I also consider that the absolute best packaging community on this planet is Fedora and Debian operating system packages. The idea of having a separate packager from the actual software making sure that the software lands well and plays nice with its neighbors is a huge feature of those communities. Those operating systems wouldn't be possible without them. The original poster also complains that there is not any versioning. If this is the case it is very sad to me and I hope that somebody can refute this claim.
3) It's not that software is released too far apart, it's that the release of software is out of the hands of developers, and packaged by a third party with dependencies that may not even be API compatible with the developer's software. Since there is no versioning dependency management for Quicklisp to leverage, all it can do is try to build your software in isolation, not check compatibility with dependencies, and certainly not runtime compatibility.
This is what I like about quicklisp. IMO other package managers don't do it this way only because it doesn't scale; pushing packaging and releasing to individual developers does.
Also, building the software "in isolation" checks at least compile-time compatibility with dependencies. IIRC someone (not Xach I think?) also runs the system tests for each system in quicklisp, which will check runtime compatibility to the extent that the tests do so.
In any case, I have literally never run into an issue with transitive dependencies not working in QL; not sure if I'm lucky or what.
Which you can use from the commandline inside of the multiplexor. Like I said it's fully featured because it's just you firing up Steel Bank. The debugger and inspector are still there.
> Since there is no versioning dependency management for Quicklisp to leverage, all it can do is try to build your software in isolation, not check compatibility with dependencies, and certainly not runtime compatibility.
The lack of versioning and dependency management is pretty dumb I'm not going to lie. I didn't expect that from a package manager.
> It's not that software is released too far apart, it's that the release of software is out of the hands of developers, and packaged by a third party with dependencies that may not even be API compatible with the developer's software.
Perhaps there are some cases where this is a problem, but in general, I firmly believe that having separate packagers is a good thing[1]. It can be annoying at times, but much more comfortable for the end user.
1: https://drewdevault.com/2019/12/09/Developers-shouldnt-distr...
What the article actually says:
"a wall of text of replies asking the user to fix their style before they can consider helping"
because they wrote their code like this or what have you:
(defun foo (arg)
(setq var (+ arg 1))
(let ((z (bar var)))
...
)
)
a common problem is some misplaced parenthesis which you can see easily if you use an editor which auto-indents the code. Encouraging newcomers to format code and learn how to have it done is good advice; it's the first survival skill.vim-slime does not connect to any Swank server. It does not understanding Lisp s-expressions. It would happily copies any random text into any random REPL and call it job done! Lisp interaction mode is much much more than just copying and pasting text around. A superior lisp interaction mode gives you live debugging, handling conditions, inspecting variables, navigating the stack frames, ... Vim-slime cannot do anything like this because, well, it is not SLIME! It just copy-pastes stuff around. Vim-slime is a disingenious and misleading name for a project that is not SLIME.
If you really want to use Vim, do yourself a favor and use https://github.com/kovisoft/slimv and experience a true Lisp interaction mode. It contains an actual Swank server and an actual Swank client that connects to the Swank server to provide an actual Lisp interaction mode in Vim just like SLIME does in Emacs!
Even better! It's not useful for just Lisp! It works for python, bash, whatever. That's not a bug, that's a feature. It's simple, lets the editor be the editor and the multiplexer be the multiplexer. It's much more "vim zen" than importing an entire repl process into the editor.
I've always known about slimv, I just like vim-slime better. My only complaint is that when it copies and paste texts around it's slower using interprocess communication than it is using TCP. But the nice thing I can see exactly what's happening instead of having it all hid from me. Makes debugging problems much easier.
Even describing slimv as a "mode" belies its emacs-ness. Vim doesn't have major and minor modes. It has insert mode and normal mode, that's it.
I don't even use fugitive. Why do it when the git CLI is faster? I've already learned the cli, why do I have to learn an entirely new set of commands to do the same things I already know how to do? Especially when I'm using vim inside GNU screen? C-a 2, boom, I'm in a CLI. Switching back and forth is a breeze. I have a few key bindings in vim that allow me to see the git blame line of a particular line, that's it.
Don't turn vim into a user interface for $x. Embed vim into other user interfaces. Vim plugin for intellij, vscode, vim inside a multiplexer, ... This works much better in my opinion.
Even though I liked the language and would have liked to use it more, I did abandon Pharo because I just couldn't imagine ever liking having to use their IDE which depends too much on the mouse. That's the only time I have done that since emacs usually handles most languages just fine.
that's how I read julia's praises, I don't think most people ignore the past here
/me goes back to old python OO crud
Why not: from Common Lisp to Julia
https://gist.github.com/digikar99/24decb414ddfa15a220b27f674...
I like Julia, but this is a point of frustration for me as well. Compilation time is fine for smaller scripts. But whenever I've tried using more powerful packages such as the SciML ones (DifferentialEquations.jl, DiffEqFlux.jl, Symbolics.jl), the precompilation time during the edit/debug cycle can be excruciating. It's a shame because the SciML packages are so amazing.
I'm waiting until Julia's static compilation process improves and is standardized. On-the-fly compilation that disappears every time you close the REPL will never be fast enough to give users a good experience when working with highly complex code.
EDIT: Just to be clear, I'm overall confident that things will improve. The folks at Julia have already made good progress in reducing precompilation times from where they used to be. Looking forward to seeing further advancements in the future.
Quote: "Coming very soon: a version of DifferentialEquations.jl that fully precompiles the solvers on Vector{Float64}, virtually eliminating the any #julialang #sciml JIT lag."
It's a point of frustration for most of the community, it's just something we're willing to put up with (and work around) for the other benefits of the language. If the tradeoff doesn't seem worth it to you, it's totally fine to wait it out until it's in a more acceptable place for you.
There's a lot of focus on improvements surrounding this in the recent and upcoming versions, precisely because of this frustration, but it's still going to be a gradual process.
100% agreed on that. I've tried a Julia alias with `--compile=min --optimize=0` options passed in to try to say "please give me responsiveness over runtime performance", but it's still not quite the smooth flow I'd like it to be.
> Dynamic Binding
Beyond performance, it sounds like dynamic binding would have the same hard-to-debug action-at-a-distance problems that global variables often land you in, so I'm not sure it's worth it. (The specific case the author mentions would also lead to type stability problems, but that's maybe beside the point.)
> Structural editing
It's hard to process things from gifs, especially since I can't tell what the starting point of the gif is. It vaguely gives me the impression of the Emmet plugin for HTML development [1].
> I am aware julia has a --lisp mode, but I have never found any documentation for it. So, I don’t agree that all the things in julia are well-documented either :).
Afaik, the `--lisp` mode is intended to be sort of an easter egg, rather than a real mode for practical coding. I doubt many people use it other than Jeff himself. :)
The author doesn't say everything in Julia is well-documented by the way, or even mention Julia documentation. There's just complaints about the Lisp ecosystem's lack of documentation, and perhaps from that an implication that Julia has better docs, but I doubt the author would say all the things are well-documented - there's still quite a way to go for that to be the case.
Overall, the article left me more curious to explore Lisp, not less. It didn't feel particularly gloomy, and exposed me to many features of the language that make me really want to try it out. I hope there's more articles like this - in the sense of being intended for a general (non-lisp) audience, and talking about specific features rather than just "it expands your mind, it's programming like you've never done before" type statements.
This is not a consequence of it being a standard, rather no one has bothered of creating a new revision of the standard, like has been happening with Ada, C, C++, JavaScript,....for the last decades.
However that is orthogonal to the language standard.
As for the standard library, and the usual bashing Python batteries get, the great thing about being in the standard library regardless how obtuse it might be, is the guarantee it exists everywhere there is a compliant implementation.
With everything else, it is hit and miss.
Arbitrary size integers written in lisp is a thing. Maybe gambit and sbcl? Can't remember offhand. Calling down to llvm.sum.i64 or w/e is very similar to calling down to x64.
Why not, rather giving up the language, just disable the debugger? Found from SO[1]
(defun debug-ignore (c h) (declare (ignore h)) (print c) (abort))
(setf *debugger-hook* #'debug-ignore)
Of course you lose a significantly strong functionality but so you do moving elsewhere.>are multiple implementations of this ANSI standard, each with their own set of features.
Can just target a single implementation. Though, similar to previous, this kinda kills the point of having a standard and multiple implementations.
Some code examples on the CLOS section and how it compares to Julia's approach will be nice and will make the points made easier to understand. The rest seem to be indeed cultural issues rather technical which for a language to be considered is also important.
This is probably because Jeff Bezanson, the creator of Julia, created a Lisp prior to Julia, which I think still exists inside Julia in some fashion
julia --lispWhat are the chances of that happening for Julia 2.0? It feels unlikely. Julia is SO close to being an objectively perfect programming language. With more and more things being compiled ahead of time, it'll replace all my needs for Go. I still might use Rust though :)
Yet, a lot of Common Lisp developers keep kneecapping themselves by imposing the portability constraint where it makes absolutely no sense whatsoever: Few will actually care in practice about the 3-4 other CL implementations that the code happens to "support" (usually, entirely untested) but the code will be bloated by the use of 3rd party half-assed underdocumented "portability" libraries.
I'm a newcomer to Common Lisp and I do agree to a certain extent with the "social problems" part of the OP critique. If I had to emphasize one, it'd be the lack of focus and polish (which includes documentation) in people's output. There are very few people in the opensource CL community that consistently produce good code and that's a major problem.
Not true for c/c++ (clang+clang/osx, gcc, msvc, icc - ed: see also stdlib, libc), Java (fewer now, but still many implantations of compiler and vm), Javascript, scheme, standard ml...
Arguably it's not even true for Python. Ruby has many implantations, but my impression is that mruby and jruby are mostly insignificant wrt the average ruby programmer. I would say pypy sees more real-world usage, maybe?
C++ changes "the standard" every couple years. When someone tells me they "know" C++ I have to ask which "standard" they "know".
Common Lisp code I wrote in the last century runs unchanged today.
So the complaint about Common Lisp being stuck in the past is actually a feature, not a bug.
When Julia settles on a standard (and only one standard) then it will be worth the learning investment. When that happens I can write code that will run without change in 2070.
The goal for a 'standard' is not ossifying a language. Don't pretend that Python3 is in any way related to Python. Call it Snake or something else. Then 'python' code continues to work and 'snake' continues to work.
The confusion, especially evident in C++, is that 'C++' is at least half-a-dozen languages related by chance. When asked if you know C++, you really should reply with the 'standard' that you claim to know. There are 6 C++ "standards" that I'm aware of. I understand there is a 7th due to arrive in 2023. I wonder if 'concepts' will be in the new 'standard'. If so, do you know what it means to inherit 'up the add chain' versus regular inheritance? If not, can you still claim to 'know C++'?
It takes a LONG time to get "command of a language". Reading other people's code is a great way to see how much you don't know. For example, did you know that in C++ you can dynamically create a class and an instance IN THE ARGUMENT LIST OF A FUNCTION? It can take years to really "know" a language, much longer than the change time of languages.
On one hand, it clearly shows that there's some trickery going on and you can't expect referential transparency.
On the other hand, it means that you can't write a DSL that has a "native" look and feel.
This was appalling to me coming to CL from languages with a lot of control over dependencies. It's essential that I can pin versions and ensure that I am getting the correct source code.
However lately I have been playing around with Guix System and now I'm wondering if the Guix package manager is the "missing" killer package manager for CL libraries (or for most any language).
Anyway, clearly I have more to explore with the CL ecosystem, but the point of my comment was really that I am surprised that a language as old (or venerable) as Common Lisp doesn't seem to have already sorted out strong package versioning and cryptographically verifiable dependencies. The fact that using HTTPS is sort of new is concerning. Maybe the language just comes from more trustworthy days in general, but my paranoia has problems with that these days. I see CLPM has a "beta" warning, mostly one author, and 14 stars (for what that's worth). It seems there is still a lot of work to be done in this area.
Despite all that, I would recommend to anyone to try CL for all its other advantages. Other tools (such as my suggestion with Guix) might be leveraged to make up for any shortcomings until good "native" solutions are sorted out (assuming I'm not completely misunderstanding the state of affairs).
The combination of SLIME/GNU Emacs and SBCL has some unique features (and is really a very useful combination), but the whole integrated development feeling one won't get from it. For example the LispWorks IDE is completely written in itself, is fully GUI based and is also in one application. Thus the cross-platform GUI system used to write the IDE is also available to the application developer. GNU Emacs OTOH is an external application, not written in Common Lisp and with a clunky user interface.
Then there is a path of older and mostly abandoned, but powerful and/or very usable user interfaces: examples are Xerox/Medley Interlisp (https://interlisp.org), Symbolics Genera, Macintosh Common Lisp and others.
[edit] What about Computer Algebra systems? Can I just interface with Sagemath, Maxima or Sympy somehow?
2. Matrices and linear algebra has only rudimentary support in Lisp. It's better than nothing but it's worse than NumPy. MAGICL, Numericals, LISP-STAT, and NUMCL are four such libraries.
3. To my knowledge, minimal/toy implementations of auto diff exist in Common Lisp, but nothing big or serious. Scheme was actually a real hotbed for autodiff research, by Pearlmutter, Siskind, et al.
4. Two of the historically best computer algebra systems are written in Common Lisp: Maxima (derived from MACSYMA of the old days) and FriCAS (derived from AXIOM of the old days). These systems basically build a computer algebra programming language and engine on top of Lisp.
Regarding 4, I'd like to use these CASes from within a library. A bit like how you can use Sympy as a library within Python.
It’s a shame to see such posts as you were a cordial and enjoyable member of the IRC community for quite some time. For me, it’s one of the better IRC channels out there and I learnt a lot from the PROFESSORS of computer science who regularly helped newcomers in the channel #clschool. [lisp123]
Otherwise glad to see you have found something enjoyable and curious on how you have pivoted away from CLOS, maybe I should investigate Julia too
can you please elaborate on this conclusion - "better off using another language"? i find it interesting because i happen to fit into this category - ie writing performant code in cl (sbcl). besides sbcl no other implementation interests me (actually maybe CLASP) and i care very little if my code is portable; hence marked as cl (sbcl). sbcl allows me to do all sorts of optimizations that not even julia has. and cl with emacs+slime is to me by far the most enjoyable hacking experience
the fact that you are writing a graphics engine (which is hardware dependent if performance is what you want) suggests to me that you too should not spend so much time on portability. i think implementation specific libraries in cl should be welcomed. like with people, if you try to get everyone to like you you are not going to get very far
This is such a nonsensical statement. Guess Julia doesn't have this problem because it only has one single implementation!
In Common Lisp you can make a program that starts in milliseconds, from scratch; no Lisp stuff in RAM, other than your OS's buffer/file caches being warm. The same was true twenty years ago or more already.
The author doesn't mention a few helpful things:
- editor support: https://lispcookbook.github.io/cl-cookbook/editor-support.ht... Emacs is first class, Portacle is an Emacs easy to install (3 clicks), Vim, Atom support is (was?) very good, Sublime Text seems good (it has an interactive debugger with stack frame inspection), VSCode sees good work underway, the Alive extension is new, usable but hard to install yet, LispWorks is proprietary and is more like Smalltalk, with many graphical windows to inspect your running application, Geany has simple and experimental support, Eclipse has basic support, Lem is a general purpose editor written in CL, it is Emacs-like and poorely documented :( we have Jupyter notebooks and simpler terminal-based interactive REPLs: cl-repl is like ipython.
So, one could complain five years ago easily about the lack of editor support, know your complaint should be more evolved than a Emacs/Vim dichotomy.
- package managers: Quicklisp is great, very slick and the ecosystem is very stable. When/if you encounter its limitations, you can use: Ultralisp, a Quicklisp distribution that ships every 5 minutes (but it doesn't check that all packages load correctly together), Qlot is used for project-local dependencies, where you pin each one precisely, CLPM is a new package manager that fixes some (all?) Quicklisp limitations
> [unicode, threading, GC…] All of these features are left to be implemented by third-party libraries
this leads to think that no implementation implements unicode or threading support O_o
> most of the language proper is not generic
mention generic-cl? https://github.com/alex-gutev/generic-cl/ (tried quickly, not intensively)
Documentation: fair points, but improving etc. Example of a new doc generator: https://40ants.com/doc/
Also I'd welcome a discussion about Coalton (Haskell-like type system on top of CL).
It just sits there like its not something most high-level languages have ignored for decades. ;)
This made me chuckle.
But this post did help me understand how Julia is Lisp done right in some specific ways, and also understand the appeal of Lisp as a programming language.
At least it survives as open source project.
The main issues for me: The function(object) is bad for readability and IDE completion. No interfaces. 1-based indexing.
When I use Swift, I'm not missing much from Julia of in terms of core language design. I'm missing the REPL and some parts of the ecosystem.