Different behavior between compiled and uncompiled code
Different behavior between compiled and uncompiled code
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
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
Re: Different behavior between compiled and uncompiled code
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?
Which lisp implementation are you using? Do all your files have something like (in-package #:package-name) near the top?
Re: Different behavior between compiled and uncompiled code
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?
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?
-
- Posts: 406
- Joined: Sat Mar 07, 2009 6:17 pm
- Location: Brazil
- Contact:
Re: Different behavior between compiled and uncompiled code
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):Ben wrote:Is it possible to get two copies of symbols, if i load compiled code in two different packages?
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"
Re: Different behavior between compiled and uncompiled code
I'm not sure of your purpose since you haven't said anything about what your doingBen wrote:Thus, i am not able to put in-package-calls into my code, because i have to use the code in different packages.
![Neutral :|](./images/smilies/icon_neutral.gif)
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)
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
Re: Different behavior between compiled and uncompiled code
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.
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.
-
- Posts: 406
- Joined: Sat Mar 07, 2009 6:17 pm
- Location: Brazil
- Contact:
Re: Different behavior between compiled and uncompiled code
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:
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
(lambda ()
(let ((*special-var1* value1)
(*special-var2* value2))
(main-function))))
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*))
Re: Different behavior between compiled and uncompiled code
Well, the application has about one thousand global variables, parameters and constants. ![Wink ;)](./images/smilies/icon_e_wink.gif)
![Wink ;)](./images/smilies/icon_e_wink.gif)
Re: Different behavior between compiled and uncompiled code
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.Ben wrote:Well, the application has about one thousand global variables, parameters and constants.