4 ms·
I've tried it dozens of times. I tried it this week and gave up again after several hours. As a language and technology it's way better than the alternatives,
by jampekka 6y ago
I've tried it dozens of times. I tried it this week and gave up again after several hours.
As a language and technology it's way better than the alternatives, but usability of Julia as a programming language is broken by the ridiculous startup latency. I'm sure it's not even really hard to fix (at least by some caching hacks), but for some reason the Julia community is actively resisting such fixes.
And don't give me REPL. REPL is a fundamentally broken approach to programming, and REPL people just keep looking for excuses to keep using it.
Edit: And if you give me REPL, I can answer that I have tried it too. It's broken as well. Revise.jl breaks constantly with anything non-trivial. And with the effort going to horrible hacks like Revise.jl, I'm sure a simple caching of compilation results between calls would be nothing. It seems to be something ideological.
- Sukera 6y agoIf you don't mind me asking, how are you using julia? Are you using modules to wrap your code and functions to structure it, or are you just running one big script in top level scope? Aside from compiler improvements, most caching related optimizations are happening on the module level, because that's where namespaces are seperated.
- jampekka 6y agoI'm not using modules. I usually start with one file with a demo or similarly named function that is called if the file is called as an entry point (like if __name__ == '__main__', except Julia makes it even worse). First the "actual" code is in separate functions in that file. No global state. I tend to refactor code out of there to separate files, and then somehow import it. An ugly way is include, and I've tried Revise.jl with includet. But I think the least ugly approach is the @from macro from here: https://github.com/Roger-luo/FromFile.jl https://github.com/Roger-luo/FromFile.jl Judging from some opinion in bug trackers, this is probably gonna get totally shunned by core devs and they'll keep on bikeshedding about the import stuff forever. With this setup I have about 400 lines of code in three files. It compiles for 15 seconds. After every single change, and actually without any changes too. I think performance wise this should be equivalent to using modules, but saving some pointless ceremony.
- Sukera 6y agoI'm using `!isinteractive() && main()` as my `if __name__ == '__main__'` equivalent, not sure how that's even worse? It's not equivalent no - include doesn't introduce a namespace and neither does includet. Compiled stuff from packages (=modules with a Project.toml) is cached between runs, scripts just don't have that luxury of seperation. @from doesn't look into the files you're including and (somewhat simplified) verbatim pastes the code into your "main" file. I don't think it's a lot of "pointless ceremony", especially since it keeps dependency management on a per project basis easy, is just a `]generate MyPkg` away and allows compiled code to be cached If you don't want to use projects, that's fine - but please do so in a constructive manner and don't be surprised that the most common workflow (wrapping things in a package) gets more attention sooner. That just signals some disregard for other peoples' needs & wants, even if that's not intended.
- jampekka 6y ago!isinteractive() && main() doesn't probably work for my case. Oftentimes my files may have a main of their own, but that isn't called if the file is just imported. I don't use Julia interactively anyway (I've explained why many times in this thread). (Edit: the equivalent Julia chant is `abspath(PROGRAM_FILE) == @__FILE__,` IMHO slightly even more obtuse than Python's, but this is a minor detail). If a "package" is used only by me and only from files controlled by me, Project.toml is clearly pointless ceremony. And `]generate MyPkg` too, and assumes REPL on top. Python manages this (albeit with some stupid arbitrary restrictions) fine, Node manages this fine. The compiler doesn't need that stuff for anything. I didn't look into the implementation of @from, but I picked it up from a huge bikeshedding bug (still open, from 2013...) about local module imports, and assumed it's doing imports instead of including, as it also has a separate namespace. From the code [2] it's not clear to me exactly what it does when, but one branch seems to be generating a module with the code imported on the fly. Not sure this should be any different than any other module for the compiler. Are you sure you're not talking out of your ass on this one? I don't care if people for some reason want to write their pointless ceremony, but what I don't understand is that people are so jealous of it that they insist of pushing it on everybody else too. I just want to somehow get access to those symbols defined in another file, why does this need more than the path of the file? I'm sure using just files-as-modules would probably be less work for the compiler, and it's easy to have a byzantine package ceremony on top if you want (Python has dozen or so available, so lots to draw from). [1] https://github.com/JuliaLang/julia/issues/4600 https://github.com/JuliaLang/julia/issues/4600 [2] https://github.com/Roger-luo/FromFile.jl/blob/master/src/FromFile.jl https://github.com/Roger-luo/FromFile.jl/blob/master/src/Fro...
- cbkeller 6y agoI’m always amused to see these “I’m sure caching wouldn’t even be a hard fix, the community must be resisting it” takes. Feel free to show me the PR’s that have have been rejected that would have solved the problem. Or if you think it’s easy, feel free to make that PR yourself. As the quote goes, “There are two hard problems in programming: cache invalidation, naming things, and off-by-one errors”. This is cache invalidation.
- jampekka 6y agoI will probably give it a go when I have some time to spare. I don't expect to get a PR through, or even want one. Perhaps I'll release it as a package if it works at all. Cache invalidation is not always that hard. For example pure functions are more or less trivial to cache, and you don't even have to do any explicit invalidation. Perhaps do some LRU type pruning if the disk starts to fill up. I know next to nothing about Julia's internals, but given packages like Revise.jl, PackageCompiler.jl and SnoopCompile.jl are even possible, I don't think it can be that hard. Dumb caching should be a lot easier than any of these. I may well be wrong, and that nobody has done this yet is a hint to me being wrong. But I think another scenario may be that Julia ecosystem is so hung up on REPLs and notebooks that this case just gets no attention. And very few non REPL-or-notebook people hang around long enough to get to know the internals at all. Maybe I'm just desperate enough? There's also another possibility, which may sound bizarre but I think is possible. At some level people who come from scripting language background think that long compile times is a sign of a "real language". This is somewhat prevalent in e.g. Javascript scene, where more and more byzantine compilation systems are introduced for a language (or platform) that works just fine without compilation (or can do very fast on-the-fly "AOT" if needed).
- gugagore 6y agoWhat do you prefer as an alternative to a REPL? How do you interact with your programs? What seems broken to me about REPLs is how text-centric they usually are. But I want to be able to easily introspect and play with my programs, and REPLs are one way to do that. Really good debuggers and environments for static languages are "another" way.
- jampekka 6y agoI just make programs that have an "entry point" (e.g. main() in C or if __name__ == "__main__" in python) and run them off the shell. Oftentimes with some arguments. This is how I interact with most of my programs, and it works fine for my own ones too. I agree that this is probably not for everybody, i.e. if you're not used to the CLI workflow. And admittedly it would be sometimes nice to have e.g. embedded graphics, but unfortunately the troubles usually outweigh the benefits (looking here at emulating damn 70's terminals too...). I mostly do the introspection with print, dir and help straight in the code. Not ideal, but rarely fails you, and I've yet to find a debugger GUI or IDE that isn't more trouble than it's worth. Something like autoupdating RMarkdown/Sweave/Pweave/etc would probably work often as well. I sometimes do use Pweave, although it tends to be a bit buggy as well, and doesn't have any caching logic (although it's easy to use your own). Sadly most efforts seem to go to Jupyter notebooks and such, whose state/code inconsistency are simply a non-starter if one wants to keep some sanity.
- gugagore 6y ago> I mostly do the introspection with print, dir and help straight in the code. This means you have to change your code in order to debug it. And you have to know what you're debugging before you change your code. This is really, in my opinion, much less than ideal, because you have to iteratively instrument your code while you figure out what is wrong. It's a cycle of You print out the first suspect thing, then that produces 5 potential suspects, and you have to decide which one to print next, or print all of them. You're absolutely right that it rarely fails you, and so I surely want that facility to be at my finger tips. But getting a text representation of a value is literally 33% of what a REPL is for.
- socialdemocrat 6y agoPeople have different style and preferences. I have programmed for over 30 years and I find that REPL based development in Julia beats anything else I have tried in term of productivity, and I have tried a ton of tools, IDEs and languages. But sure it may not fit your particular preference or it may be that you have simply not learned to use it effectively. It takes some time to work effectively in a REPL style. It took me some years. Not every language is suited for REPL development. Julia, LISP and Haskell seem quite well suited. I don’t have quite the same good experience with Python e.g.
- jampekka 6y agoIt probably depends also on what you program. If the task is simple enough and doesn't need much revisiting, REPL is probably fine. But OTOH, just writing the code for a simple case and running it isn't too bad either. How do you persist and document your code with REPL-development? Do you log the commands to some separate file? How do you recreate the REPL state if it crashes or you have to reboot? How do you make sure the REPLs state is what you think it is? These are (some of) the concrete problems that I see with REPL, and that don't exist for program based workflow. And I think these are fundamentally impossible to solve for REPL, and very important for e.g. reproducibility (and IMHO sanity).
- oxinabox 6y agoGenerally I am copy-pasting code out of a WIP package to test out an idea as I go. So the code is already being written in a file. Or I am using Juno/VS-Code/Vim-Slime to simplify the copy-paste. Other times I have the package I am editing loaded with Revise.jl active and I am calling in and trying out the methods I am concurrently writing in my text editor. It's more like TDD than anything else. It's got that same quick back and for of run, write, run write. But a but more interactive. (Note I am not saying that is TDD -- it isn't -- tests are not nesc written or saved. Though I do often use this while doing TDD to run a test I have written)
- _coveredInBees 6y agoI just don't think you've tried or been exposed to responsible REPL prototyping and development. Like sure, you could have all sorts of issues if you use REPL irresponsibly and pollute your state with undocumented code and side effects. But if you use it responsibly, it can be really fast and efficient when prototyping things... Even complex subsystems in a larger codebase. I've prototyped entire reimplementations of SOTA object-detection DNN algorithms in Pytorch with no issues and have been far more productive because I can develop functionality in small chunks while intimately understanding the problem at hand and associated data and then immediately graduate it to a working script/module/package as I go along. For more complex things, I can even have a stub for a function I am developing and breakpoint into it and then I prototype the functionality in the REPL and that is wayyy faster and less bug prone than trying to go at it blindly in your IDE without being able to experiment and verify your code as you develop it.
- krastanov 6y agoI think you are being unfair. Just look at the various Julia forums: addressing startup latency has been the main focus since 1.3 and each of the version since then (especially the 1.6 beta) have had significant improvements. Same with the REPL comments: you can easily just write scripts instead of using Revise/Pluto/IJulia or another REPL approach.
- jampekka 6y ago> Same with the REPL comments: you can easily just write scripts instead of using Revise/Pluto/IJulia or another REPL approach. The problem is that I can't. The startup latency makes using scripts practically impossible. I think it could be relatively easy to fix (hack). I'll shut up about this on the very second there's some way to get same magnitude of latency with scripts as there's with REPL.
- oxinabox 6y agoWell then, DaemonMode.jl as a hack to run scripts as fast as in REPL by leaving a julia Daemon running and just sending work to it https://github.com/dmolina/DaemonMode.jl https://github.com/dmolina/DaemonMode.jl