Different behavior between compiled and uncompiled code

Discussion of Common Lisp
Post Reply
Ben
Posts: 6
Joined: Thu Jul 02, 2009 2:28 am
Location: Germany

Different behavior between compiled and uncompiled code

Post by Ben » Thu Jul 02, 2009 2:41 am

Hello,

is it possible that loading a compiled file exhibits the same behavior as loading its source file?

I experience diffent behavior if i use custom packages. In the compiled file the package informations during compile-time is contained.
If during load-time i have a different package as in compile-time i got problems, because the file is read in the package that was active during compile-time and not in the package which is active during load-time.

The key question is: Is it possible that loading a compiled file exhibits the same behavior as loading its source file?

Thanks

Ben

nuntius
Posts: 538
Joined: Sat Aug 09, 2008 10:44 am
Location: Newton, MA

Re: Different behavior between compiled and uncompiled code

Post by nuntius » Thu Jul 02, 2009 1:18 pm

Yes it is possible, otherwise compiled files wouldn't be very useful. As you found, there are cases where they differ.

Which lisp implementation are you using? Do all your files have something like (in-package #:package-name) near the top?

Ben
Posts: 6
Joined: Thu Jul 02, 2009 2:28 am
Location: Germany

Re: Different behavior between compiled and uncompiled code

Post by Ben » Fri Jul 03, 2009 3:13 am

Well, i use LispWorks.

In my sourcecode no in-package-calls are contained.

The common use of packages is to make functions and symbols 'visible' and usable, but in my case that is not enough unfortunately.
If i load uncompiled code into two different packages, i got two copies of the symbols, which i can use in both packages independantly. And that is exactly the fact i need. Thus, i am not able to put in-package-calls into my code, because i have to use the code in different packages.

Is it possible to get two copies of symbols, if i load compiled code in two different packages?

gugamilare
Posts: 406
Joined: Sat Mar 07, 2009 6:17 pm
Location: Brazil
Contact:

Re: Different behavior between compiled and uncompiled code

Post by gugamilare » Fri Jul 03, 2009 6:41 am

Ben wrote:Is it possible to get two copies of symbols, if i load compiled code in two different packages?
I am not sure, but I don't think so. If you want to use the file with a fixed number of packages, you cam compile the file more than once, each time with *package* bound to a different package. For that purpose, you can use the code below (not tested):

Code: Select all

(defun make-compilations-of (file)
  (let ((*package* *package*) ; the current package needs to be restored after the function returns
         (path (pathname file)))
    (in-package :foo)
    (compile-file file
      :output-truename (make-pathname :defaults path
                         :name (concatenate 'string (pathname-name path) ".foo"))
                         :type "fasl") ; outputs a compiled file with extension ".foo.fasl"
    (in-package :bar)
    (compile-file file
      :output-truename (make-pathname :defaults path
                         :name (concatenate 'string (pathname-name path) ".bar"))
                         :type "fasl"))) ; outputs a compiled file with extension ".bar.fasl"

smithzv
Posts: 94
Joined: Wed Jul 23, 2008 11:36 am

Re: Different behavior between compiled and uncompiled code

Post by smithzv » Fri Jul 03, 2009 7:37 am

Ben wrote:Thus, i am not able to put in-package-calls into my code, because i have to use the code in different packages.
I'm not sure of your purpose since you haven't said anything about what your doing :| , but this sounds wrong. The only thing I can figure is that you want separate copies of the symbols because you want to mutate these symbols or the data they are associated with. Is this right? I mean are you trying to do something like this:

Code: Select all

file1.lisp:

(defun my-func (x) (* 2 x))

(defparameter *a-vector* (vector 1 2 3))

end-of-file1

repl:
(in-package :pkg1)

(load #p"file1")
(my-func 5)
==> 10
(setf *a-vector* (vector 3 2 1))
==> #(3 2 1)

(in-package :pkg2)

(load #p"file1")
;; Let's change the definition of PKG2::MY-FUNC
(defun my-func (x) (* 3 x))
(my-func 5)
==> 15
*a-vector*
==> #(1 2 3)

;; PKG1::MY-FUNC still has the same definition
(pkg1::my-func 5)
==> 10
;; PKG1::*A-VECTOR* still has the changed value
pkg1::*a-vector*
==> #(3 2 1)
I can definitely understand how you would desire to do this in the case where you have a closure as a top level form; you would need two independent copies of these closures or they may interfere with each other.

If this is the sort of thing you want, I think you should be creating these symbols via a function call (a function that is defined in file1.lisp), not by loading file1.lisp and having LOAD do your dirty work for you. It is hard to write an example when I don't have something to work from, but if I wanted to have multiple instances of some data, I would provide a function that either returns newly allocated data or takes symbols and defines sets newly allocated data to those symbols. I.e. instead of using (load #p"file1") to get a copy of all of the symbols you want, I would have a function like (init-file1-environment ... some args...) that returns or defines the proper environment for whatever work you want to do. In addition, if make your function just returns the proper objects, you are most of the way to providing a WITH-FILE1-ENVIRONMENT macro.

Zach S

Ben
Posts: 6
Joined: Thu Jul 02, 2009 2:28 am
Location: Germany

Re: Different behavior between compiled and uncompiled code

Post by Ben » Wed Jul 08, 2009 6:55 am

First of all, Thanks for all the answers.

Well, i have to investigate possibilities how a linear non-thread-based application can be used in a multi-thread or multi-processor environment. The application itself is not parallelized, but it should be possible that two or more instances of the application are running at the same time; in the same process.
The application is quite huge (a few MB sourcecode) so the source-code should not be changed.

The in my opinion best solution is the package-approach. I compile the code for x packages, so that the application is able to run x times parallel (each in a different thread).
To make it possible to run the application in parallel, i looked for a possibility to duplicate the whole datastructure and packages made this possible. Well this is not the common use of packages, but it works fine, as i can see.

gugamilare
Posts: 406
Joined: Sat Mar 07, 2009 6:17 pm
Location: Brazil
Contact:

Re: Different behavior between compiled and uncompiled code

Post by gugamilare » Wed Jul 08, 2009 7:58 am

Do you really need to compile the same code in two packages to parallelize the application? You can also locally bind all special variables and everything else should work just fine:

Code: Select all

(make-thread
  (lambda ()
    (let ((*special-var1* value1)
           (*special-var2* value2))
      (main-function))))
With the advantage of not needing to have duplicates of the functions.

The package Bordeaux Threads (which is a compatibility libraries for using threads) have the function make-thread with a keyword argument :initial-bindings which allows you to supply which variables you want to rebind and their values, and a variable *standard-io-bindings* which provides the variables that can conflict between threads. So, instead of the code above, with Bordeaux Threads you do

Code: Select all

(make-thread #'main-function
    :initial-bindings (list* (cons '*special-var1* value1)
                             ;; note the quote in the name of the variable
                             (cons '*special-var2* value2))
                             *standard-io-bindings*))

Ben
Posts: 6
Joined: Thu Jul 02, 2009 2:28 am
Location: Germany

Re: Different behavior between compiled and uncompiled code

Post by Ben » Thu Jul 09, 2009 6:19 am

Well, the application has about one thousand global variables, parameters and constants. ;)

dmitry_vk
Posts: 96
Joined: Sat Jun 28, 2008 8:01 am
Location: Russia, Kazan
Contact:

Re: Different behavior between compiled and uncompiled code

Post by dmitry_vk » Thu Jul 09, 2009 6:41 am

Ben wrote:Well, the application has about one thousand global variables, parameters and constants. ;)
All it takes is just to have a function that will gather a list of package's special variables and run the application instance inside a progv.

Post Reply