News for hackers. Stuff that matters.
Re:Why I haven't jumped ship from Common Lisp to Racket just... by lottin on Wednesday August 23, 2017 @04:16AM (#15079570)
> trivial utilities for interactive use from the shell command-line with an "instantaneous" feel

Last time I checked CL images were huge though. Something like 24MB for a "hello world" executable, even bigger with some compilers.

Re:Why I haven't jumped ship from Common Lisp to Racket just... by IronBacon on Wednesday August 23, 2017 @05:24AM (#15079867)
With SBCL and Linux kernels with binfmt_misc support enabled (module or compiled) you can execute FASL file from command line, using the same SBCL core for all the executables and, I would add, with an "instantaneous" feel. ^__^

With Debian it should work out of the box, on other distributions it probably needs to register a wrapper/trampoline with the binfmt_misc infrastructure.

FWIK running instances don't share the same core in RAM though.

  $ cat hello-world.lisp                                                     /tmp
  (print "Hello. World!")
  $ sbcl --noinform                                                          /tmp
  * (compile-file "hello-world.lisp" :output-file "hello-world")
  ; compiling file "/tmp/hello-world.lisp" (written 23 AUG 2017 11:09:24 AM):
  ; compiling (PRINT "Hello. World!")
  ; /tmp/hello-world.fasl written
  ; compilation finished in 0:00:00.001
  #P"/tmp/hello-world.fasl"
  NIL
  NIL
  * %                                                         
  $ chmod +x ./hello-world.fasl                                              /tmp
  $ ls -lh hello-world.fasl                                                  /tmp
  -rwxr-xr-x 1 user user 330 Aug 23 11:17 hello-world.fasl*
  $ time ./hello-world.fasl                                                  /tmp

  "Hello. World!" ./hello-world.fasl  0.00s user 0.00s system 44% cpu 0.009 total
  $                                                                          /tmp
Edit for clarifications and fixing formatting
Re:Why I haven't jumped ship from Common Lisp to Racket just... by lottin on Wednesday August 23, 2017 @05:49AM (#15080002)
Didn't know that.
Re:Why I haven't jumped ship from Common Lisp to Racket just... by flavio81 on Wednesday August 23, 2017 @08:52AM (#15081084)
> Last time I checked CL images were huge though. Something like 24MB for a "hello world" executable, even bigger with some compilers.

You need to consider that Common Lisp includes a runtime, and this is a essential part of the goods of Common Lisp. Whenever you create a Common Lisp program, you also "embed" the runtime, and the runtime allows you to do wonderful stuff within the running code, like for example, compile code on the fly, replace function with new version (while the program is running), replace class instances with new versions of the class (while the program is running), all sorts of enforcements of the required data type for actual data* (while the program is running),

and,

it has the wonderful "conditions/restart" system. The combination of the latter with all the former, allows you to 'correct' or 'patch' a running program without really needing to recompile the whole program or even restart the running program. Famous story of usage of this feature is using it to patch a bug on the Common Lisp program for the autopilot of the NASA Deep Space One spaceship. The NASA engineers were able to debug and then fix the program while having the DS1 in space with the code running.

So, the FASL (fast load) file is basically similar to the memory file created whenever you put a laptop into "hibernation" mode; it allows you to quickly load the whole runtime, plus your code, *plus the instances of your objects or data, if needed, just straight into memory. This is how "fast load" is achieved.

Actual RAM usage of Lisp will vary with implementations; again, as I mentioned in another post, you pick the implementation that suits your particular needs.

Re:Why I haven't jumped ship from Common Lisp to Racket just... by KirinDave on Wednesday August 23, 2017 @11:24AM (#15082213)
> You need to consider that Common Lisp includes a runtime, and this is a essential part of the goods of Common Lisp. Whenever you create a Common Lisp program, you also "embed" the runtime, and the runtime allows you to do wonderful stuff within the running code, like for example, compile code on the fly, replace function with new version (while the program is running), replace class instances with new versions of the class (while the program is running), all sorts of enforcements of the required data type for actual data* (while the program is running),

Lots of other people do this without massive executables to distribute, though. CLs are inconsistent on how they can distribute base images and executables. For example, Java's compiler is a code segment you an link in if you want to carry it with you.

Re:Why I haven't jumped ship from Common Lisp to Racket just... by flavio81 on Wednesday August 23, 2017 @12:13PM (#15082715)
> though. CLs are inconsistent on how they can distribute base images and executables

There is only one Common Lisp, the 1994 ANSI Standard.

There are many implementations and they give you diverse options of delivering. For example if you want good options to package an executable, I think LispWorks has lots of options for specifically this need.

Re:Why I haven't jumped ship from Common Lisp to Racket just... by KirinDave on Wednesday August 23, 2017 @12:24PM (#15082806)
You know exactly what I meant, flavio81. Obviously.

> For example if you want good options to package an executable, I think LispWorks has lots of features.

It had 2 alternatives. I know, because I shipped some stuff to prod for Powerset on LW back in like 2009? We ultimately stopped using it precisely because we shipped less bytes more quickly with Java and Ruby.

> As for Java, to execute a Java class you need a JRE (java runtime environment), which is not small at all, so I am not sure if it gives you a big advantage.

I'm surprised to hear you say this, but in the interests of completeness I'll give you a handy way to compute the difference in bytes saved.

    (defun bytes-saved (num-deploys stdenv-size)
      (* (-1 num-deploys) stdenv-size))
A similar trivial function could help you see the amount of time saved by not compiling on site, should you respond to just ship and produce images onsite.

This requirement is even more important in the world of diverse deployment techniques that expect modularized executables as a space and performance optimization. Docker, Nim, deployments around FreeBSD jails, and even package managers have dramatically improved performance if you can offer that kind of segmentation.

Re:Why I haven't jumped ship from Common Lisp to Racket just... by junke on Wednesday August 23, 2017 @12:24PM (#15082807)
You did install a JVM to run Java, didn't you? If you want to develop in Java, you need a JDK. According to this page, it amounts to 132MB:

http://www.oracle.com/technetwork/java/javase/windows-disksp...

Re:Why I haven't jumped ship from Common Lisp to Racket just... by KirinDave on Wednesday August 23, 2017 @12:26PM (#15082823)
Please see: https://news.ycombinator.com/item?id=15082806

ONE installation is inevitable. It's that very few CL-offering environments give you anything better than an image.

Re:Why I haven't jumped ship from Common Lisp to Racket just... by aerique on Wednesday August 23, 2017 @04:27AM (#15079618)
You are correct, but why is this a problem in the case mentioned by the author?

    $ cat > hello-world.lisp
    (defun main () (format t "Hello, World!~%"))
    $ sbcl 
    * (load "hello-world.lisp")
    T
    * (save-lisp-and-die "hello-world" :toplevel #'main :executable t)
    [undoing binding stack and other enclosing state... done]
    [defragmenting immobile space... 1110+19908+28500+22601 objects... done]
    [saving current Lisp image into hello-world:
    writing 4816 bytes from the read-only space at 0x20000000
    writing 2320 bytes from the static space at 0x20100000
    writing 2383872 bytes from the immobile space at 0x20300000
    writing 15190112 bytes from the immobile space at 0x21b00000
    writing 39911424 bytes from the dynamic space at 0x1000000000
    done]
    $ ./hello-world 
    Hello, World!
    $ ls -lh hello-world
    -rwxr-xr-x 1 user user 56M Aug 23 10:23 hello-world
Re:Why I haven't jumped ship from Common Lisp to Racket just... by farray on Wednesday August 23, 2017 @07:01AM (#15080365)
Executing fasls is cool, but they will start from a new empty image, and loading fasls is actually kind of slow, so if you use lots of libraries rather than write a trivial example, that may consume hundreds of milliseconds before the program actually starts. Then again, this supposes you compiled everything into a single .fasl (which ASDF makes easy). But that will be a big fasl for each program; if you want to load from libraries, then there's also the overhead of setting up and using ASDF itself, which can also be in the hundreds of milliseconds. I can imagine many ways to improve the situation, but none are cheap (e.g. implement a background daemon to serve ready executables and/or watch the source registry for modified source; or break compatibility with the entire ASDF setup, angrying the entire community).
Re:Why I haven't jumped ship from Common Lisp to Racket just... by CaptObvious2 on Friday August 25, 2017 @01:17AM (#15096287)
It's still too big, too slow [compared to gerbil] and uses a lot more memory. Gambit GC is amazingly fast, and never tenures garbage to a gen where it will collect like SBCL tends to do on many workloads. [acl/ccl/lw do not have this issue, although they are slower than sbcl]
Re:Why I haven't jumped ship from Common Lisp to Racket just... by lottin on Wednesday August 23, 2017 @04:52AM (#15079729)
It's not necessarily a problem, but personally for small utilities I much prefer something that supports #!-style scripts, like Guile or Racket, or that can be compiled into small, efficient executables. Let's say it's a matter of personal preference.
Re:Why I haven't jumped ship from Common Lisp to Racket just... by farray on Wednesday August 23, 2017 @06:50AM (#15080290)
I wrote cl-launch so you can use #!/usr/bin/cl with lots of options and write scripts that are either portable or implementation-specific (and trivially switch from one implementation to the other).
Re:Why I haven't jumped ship from Common Lisp to Racket just... by juki on Wednesday August 23, 2017 @05:06AM (#15079781)
You can use CL for #!-scripts too. SBCL has a `--script` option for running scripts. You'll probably want to create a core with whatever libraries you need for scrips, so that the start-up time will be fast. The core will be big, but it can be shared for all scripts, so that's not much of a problem.
Re:Why I haven't jumped ship from Common Lisp to Racket just... by ebzzry on Friday August 25, 2017 @06:58AM (#15097548)
I wrote a short introduction to a more portable Common Lisp scripting system—made by Fare, himself—at https://ebzzry.io/en/script-lisp/
Re:Why I haven't jumped ship from Common Lisp to Racket just... by kazinator on Friday August 25, 2017 @10:21AM (#15098628)
If you do scripting and like Lisp, you definitely should take a look at TXR.

I wrote TXR to basically be the "acceptable {awk, perl, ruby, Python, ...}" for Lisp-minded people. Well, for me, that is; but anyone else too.

Re:Why I haven't jumped ship from Common Lisp to Racket just... by kazinator on Friday August 25, 2017 @01:43PM (#15100554)
Small with CLISP. 15 years ago I developed a version control system/layer called Meta-CVS using CLISP. It compiled a custom CLISP linking set to adds some C functions, and then dropped an image (custom lispinit.mem) launched via a #! mechanism which invoked the custom CLISP executable with code linked in, and the memory image via the -M lispinit.mem option. It was small and fast enough for 2002.

I have experience deploying with Clozure on Windows. The raw memory images are large-ish, but they compress extremely well into the installer (such as NSIS). I think there is a lot of wasted space in there. Lisp images are not unlike Unix core dumps in may respects. It's similar to checkpointing a process to disk. There is a time versus speed tradeoff there; if you compress it, then you can't just map it into memory as-is.