Wiki
Download
Manual
Eggs
API
Tests
Bugs
show
edit
history
You can edit this page using
wiki syntax
for markup.
Article contents:
[[toc:]] == Porting CHICKEN 4 code to CHICKEN 5 This guide will take you by the hand and explain how to port code from CHICKEN 4 to CHICKEN 5. If your code is an egg, you might want to manually compile the source components at first before finishing up the egg itself. Please read it through and if you hit any issues not in this document which you think are important to note, add them to this page. It's a wiki after all! With your additions you'll be saving others from the same pain. If you prefer to first fix the egg's compilation infrastructure, scroll down to the [[#Re-packaging eggs|section on egg (re-)packaging]], then go back up and take care of your code afterwards. === Begin with the easy part: replacing module imports When you have some CHICKEN 4 code to port to CHICKEN 5, the best way to get started is by first installing all the eggs you know are needed. Then, in your code, replace every {{use}} and {{require-extension}} with {{import}}, and then compile the code. This should give lots of errors about unknown modules. If you are using any of the following modules from CHICKEN 4 core, these have moved to an egg so you should install the corresponding egg before proceeding: * [[/eggref/5/srfi-1|srfi-1]] * [[/eggref/5/srfi-13|srfi-13]] * [[/eggref/5/srfi-14|srfi-14]] * [[/eggref/5/srfi-18|srfi-18]] * [[/eggref/5/srfi-69|srfi-69]] Some other procedures have also been moved into eggs, but we'll deal with those later. Installing these "large" eggs will take care of fixing the bulk of your import issues. Now, after you've installed the required eggs you can recompile, and you'll typically still get errors about nonexisting core modules (like "chicken", "extras", "posix" and so on). The easiest way to get rid of this is to simply '''remove''' those modules from your import forms, and then retrying the compilation. If your code is wrapped in a module, eventually, you'll be left only with errors about missing imports, and cascade-style errors caused by missing macros (these can be very misleading, so pay attention!). For example, when I was porting the [[/eggref/5/uri-generic|uri-generic egg]], I got this list after I had replaced {{use}} by {{import}} and installed the requisite SRFI eggs: Warning: reference to possibly unbound identifier `->string' in: Warning: uri-normalize-case Warning: suggesting: `(import chicken.string)' Warning: reference to possibly unbound identifier `conc' Warning: suggesting: `(import chicken.string)' Warning: reference to possibly unbound identifier `reverse-list->string' in: Warning: uri-char-list->string Warning: suggesting: `(import chicken.string)' Warning: reference to possibly unbound identifier `string-intersperse' in: Warning: join-segments Warning: suggesting: `(import chicken.string)' Warning: reference to possibly unbound identifier `with-output-to-string' in: Warning: uri->string Warning: suggesting: `(import chicken.port)' Warning: reference to possibly unbound identifier `fprintf' Warning: suggesting: `(import chicken.format)' Warning: reference to possibly unbound identifier `out' Warning: reference to possibly unbound identifier `x' Warning: reference to possibly unbound identifier `define-record-printer' Warning: suggesting: `(import chicken.base)' Warning: reference to possibly unbound identifier `URIAuth-port-set!' Warning: reference to possibly unbound identifier `URIAuth-port' in: Warning: uri-auth->list Warning: uri-auth-equal? Warning: uri-port Warning: update-URIAuth Warning: reference to possibly unbound identifier `URIAuth-host-set!' Warning: reference to possibly unbound identifier `URIAuth-host' in: Warning: uri-auth->list Warning: uri-auth-equal? Warning: uri-host Warning: update-URIAuth Warning: reference to possibly unbound identifier `URIAuth-password-set!' Warning: reference to possibly unbound identifier `URIAuth-password' in: Warning: uri-auth->list Warning: uri-auth-equal? Warning: uri-password Warning: update-URIAuth Warning: reference to possibly unbound identifier `URIAuth-username-set!' Warning: reference to possibly unbound identifier `URIAuth-username' in: Warning: uri-auth->list Warning: uri-auth-equal? Warning: uri-username Warning: update-URIAuth Warning: reference to possibly unbound identifier `URIAuth?' in: Warning: ucdiff? Warning: uri-auth->list Warning: reference to possibly unbound identifier `password' Warning: reference to possibly unbound identifier `username' Warning: reference to possibly unbound identifier `make-URIAuth' in: Warning: authority Warning: loop Warning: reference to possibly unbound identifier `<URIAuth>' Warning: reference to possibly unbound identifier `URI-fragment-set!' Warning: reference to possibly unbound identifier `URI-fragment' in: Warning: uri->list Warning: uri-equal? Warning: update-uri* Warning: update-URI Warning: reference to possibly unbound identifier `URI-query-set!' Warning: reference to possibly unbound identifier `URI-query' in: Warning: uri-relative-to Warning: uri->list Warning: uri-equal? Warning: update-uri* Warning: update-URI Warning: reference to possibly unbound identifier `URI-path-set!' Warning: reference to possibly unbound identifier `URI-path' in: Warning: uri-relative-to Warning: uri->list Warning: uri-equal? Warning: update-uri* Warning: update-URI Warning: reference to possibly unbound identifier `URI-authority-set!' Warning: reference to possibly unbound identifier `URI-authority' in: Warning: uri-relative-to Warning: uri->list Warning: uri-equal? Warning: loop Warning: uri-password Warning: uri-username Warning: uri-port Warning: uri-host Warning: update-URI Warning: reference to possibly unbound identifier `URI-scheme-set!' Warning: reference to possibly unbound identifier `URI-scheme' in: Warning: uri-relative-to Warning: uri->list Warning: uri-equal? Warning: update-uri* Warning: update-URI Warning: reference to possibly unbound identifier `URI?' in: Warning: uri->list Warning: uri->string Warning: reference to possibly unbound identifier `path' Warning: reference to possibly unbound identifier `make-URI' in: Warning: failure29947 Warning: relative-ref Warning: uri Warning: make-uri Warning: make-uri* Warning: loop Warning: reference to possibly unbound identifier `<URI>' Warning: reference to possibly unbound identifier `define-record-type' Warning: suggesting one of: Warning: (import chicken.base) Warning: (import srfi-9) Warning: reference to possibly unbound identifier `error' Warning: suggesting one of: Warning: (import chicken.base) Warning: (import srfi-23) Error: module unresolved: uri-generic This long list looks pretty intimidating, but it's not that hard to fix, actually. The way to do that is to quickly skim the suggestions. Oftentimes you'll get lots of errors about procedures that don't directly come from missing imports, like in this case (all the URI-blabla procedures being undefined). If you look closely, you'll notice that all of these follow a certain naming pattern: {{URI-foo}} or {{URI-foo-set!}}. This points us to the fact that they are record accessors. You'll also notice the suggestion mentioning {{define-record-type}}, which is exactly what we need to import to fix all these errors. Especially when you're using defining macros like you'll see lots of these kinds of errors repeated all over the place where the definitions are used. So, be aware that this can make the output a bit confusing. If you have large macros with lots of keywords. That's why it's usually best to start getting your macro imports in order, then recompiling to get rid of all the excess noise. In my example of uri-generic, after ''just'' adding {{(import (chicken base))}}, which I prefer over {{(import chicken.base)}}, the number of warnings/errors were drastically reduced: Warning: reference to possibly unbound identifier `->string' in: Warning: uri-normalize-case Warning: suggesting: `(import chicken.string)' Warning: reference to possibly unbound identifier `conc' Warning: suggesting: `(import chicken.string)' Warning: reference to possibly unbound identifier `reverse-list->string' in: Warning: uri-char-list->string Warning: suggesting: `(import chicken.string)' Warning: reference to possibly unbound identifier `string-intersperse' in: Warning: join-segments Warning: suggesting: `(import chicken.string)' Warning: reference to possibly unbound identifier `with-output-to-string' in: Warning: uri->string Warning: suggesting: `(import chicken.port)' Warning: reference to possibly unbound identifier `fprintf' Warning: suggesting: `(import chicken.format)' Error: module unresolved: uri-generic After adding the suggested imports, the code compiled cleanly and the tests ran without problems, after I fixed a few trivial imports in the test suite. So you see, even for medium sized eggs like uri-generic, porting '''can''' be a breeze. But beware, there are situations where things can get hairier! === Fixing more missing procedures by installing eggs After you've fixed your core imports and installed the SRFI eggs, you might notice some problems if you're using particular procedures from old core modules that are no longer available. Some of those have been moved into separate eggs. If this is the case with your code, take a look through the list below. Some procedures from the "utils" module have been moved into several eggs: * [[/eggref/5/compile-file|compile-file]] * [[/eggref/5/scan-input-lines|scan-input-lines]] Some procedures from "lolevel" have been moved into an [[/eggref/5/object-evict|object-evict]] egg: * {{object-evict}} * {{object-evict-to-location}} * {{object-evicted?}} * {{object-release}} * {{object-unevict}} * {{object-size}} The following procedures from {{data-structures}} have been moved to the [[/eggref/5/queues|queues]] egg: * {{list->queue}} * {{make-queue}} * {{queue?}} * {{queue-length}} * {{queue->list}} * {{queue-add!}} * {{queue-empty?}} * {{queue-first}} * {{queue-last}} * {{queue-remove!}} * {{queue-push-back!}} * {{queue-push-back-list!}} And the [[/eggref/5/binary-search|binary-search]] procedure from {{data-structures}} has also been put into its own egg. From the {{posix}} module, memory mapped I/O has been moved into its own [[/eggref/5/memory-mapped-files|memory-mapped-files]] egg. Specifically, these procedures have been moved there: * {{memory-mapped-file?}} * {{map-file-to-memory}} * {{memory-mapped-file-pointer}} * {{unmap-file-from-memory}} Also removed from {{posix}} are the group information procedures, which have been moved to the [[/eggref/5/posix-groups|posix-groups]] egg. These are the following: * {{group-information}} * {{initialize-groups}} * {{get-groups}} * {{set-groups!}} Lastly, a few macros from {{chicken}} were moved into the [[/eggref/5/miscmacros|miscmacros]] egg: * {{eval-when}} * {{ensure}} * {{select}} === Random and random-bsd The {{random}} procedure produced very weak random numbers, so we've deleted it. Instead, you can import [[/man/5/Module (chicken random)|{{(chicken random)}}]] and use {{pseudo-random-integer}}, which should produce random numbers in the range between 0 and the number you supply (exclusive). Its argument '''must''' be an exact integer. If you were using the random-bsd egg (which produced slightly better random numbers), it's probably best to use the built-in random number generator. If before you would divide by a floating-point number to get a number in the range 0..1, you can now use {{(pseudo-random-real)}}, which will do the same thing, but in a better way. If you need to initialize the PRNG to a known state, instead of {{randomize}}, you can use {{set-pseudo-random-seed!}}, but be aware that the numbers you'll get will be different. For cryptographic uses or other uses that require "really" random numbers, you can use {{random-bytes}}, which returns numbers from the operating system's entropy source. === Fixing more subtle issues Then, there are some semantic changes. These are of course listed in the {{NEWS}} file, but let's take a look at some of the more important ones: ==== read-string returns {{#!eof}} instead of {{""}} at end of file The title says it all: The [[/man/5/Module (chicken io)#read-string|read-string]] procedure now returns {{#!eof}} when the end of file is hit, instead of an empty string. This is more consistent and allows one to distinguish between a successful read of zero characters and an exhausted file descriptor. This is listed first because it's quite tricky and can cause very subtle bugs, so be very careful about this one in particular. I hope you have a good test suite! :) ==== '...'expected syntax-transformer, but got: #<procedure (? f r c)> You are probably using a define-syntax call with a procedure as argument. This has been deprecated. You need to wrap this inside a er-macro-transformer or ir-macro-transformer expression. ==== process, process* and process-execute argument type change The third argument for these three procedures is now an association list instead of a list of strings. For example, this CHICKEN 4 code: <enscript highlight="scheme"> (process-execute "/usr/bin/env" '() '("VARIABLE=VALUE")) </enscript> Becomes this for CHICKEN 5: <enscript highlight="scheme"> (process-execute "/usr/bin/env" '() '(("VARIABLE" . "VALUE"))) </enscript> ==== repository-path type change The (repository-path) parameter, living in the (chicken platform) module, now contains a list of strings instead of a string, representing the multiple repository directories requested by the user. Change in the code would look like this, for example: <enscript highlight="scheme"> ;; Changing this: (repository-path "awesome-repository") ;; to this (repository-path '("awesome-repository")) ;; if you want to replace the user choice ;; or (repository-path (cons "awesome-repository" (repository-path))) ;; if you want to extend it </enscript> ==== FFI integers arguments require fixnum or bignum values Now that support for the full numeric tower, support for floating point values behaving like integers has been removed. The FFI layer does not convert flonum to integers when passing them as arguments to C functions any longer. <enscript highlight="scheme"> ;; As an example: ;; might come from an external library, like JSON parsing (where every number is floating point) (define milliseconds-time 1534096420492.0) ;; CHICKEN 4 way ; (seconds->local-time (/ milliseconds-time 1000)) ;; CHICKEN 5 way (seconds->local-time (inexact->exact (round (/ milliseconds-time 1000)))) </enscript> ==== Linking to external libraries In CHICKEN 5, the {{-l}} flag was removed, you now have to use {{-L -llib}}. For example: <enscript highlight="sh"> # Something compiled like so: csc program.scm -lncurses # Would now be compiled like this: csc program.scm -L -lncurses </enscript> ==== Manually created record instances In CHICKEN 5 structure tags created by records (as defined with {{define-record}}, etc. are by default qualified with the module name. Sometimes code creates these record instances manually (i.e. by using {{##sys#make-structure}}, which must take this qualification into account, e.g.: <enscript highlight="scheme"> (module foo () (import scheme (chicken base)) (define-record baz) (print (eq? (make-baz) (##sys#make-structure 'baz)))) ; ==> prints "#f" </enscript> === Re-packaging eggs If your code is an egg, you'll have to rewrite your setup file into the new "declarative" format. There's a [[/man/5/Extensions#creating-eggs|short description]] on how to create eggs for CHICKEN 5 in the manual, as well as a [[/man/5/Egg specification format|complete reference]] on the new file format. Basically, the new way to make an egg involves writing a {{.egg}} file. This looks a lot like the old {{.meta}} file, with the author, name, license and dependency declarations. Added to this are "components", which make up the egg's sources. For simple eggs, this is also trivial. Here's uri-generic's old {{.meta}} file: <enscript highlight="scheme"> ((egg "uri-generic.egg") (license "BSD") (category web) (needs matchable) (test-depends test) (author "Ivan Raikov, Peter Bex, Seth Alves") (synopsis "URI generic syntax (RFC 3986) parsing and manipulation.")) </enscript> And its {{.setup}} file: <enscript highlight="scheme"> (standard-extension 'uri-generic "2.43") </enscript> After porting this to CHICKEN 5's {{.egg}} file, you get: <enscript highlight="scheme"> ((license "BSD") (category web) (dependencies matchable srfi-1 srfi-13 srfi-14) (test-dependencies test) (author "Ivan Raikov, Peter Bex, Seth Alves") (synopsis "URI generic syntax (RFC 3986) parsing and manipulation.") (components (extension uri-generic))) </enscript> As you can see, for eggs consisting of a single file, this is very straightforward: just add any missing egg dependencies for the stuff that has moved out of core, remove obsolete forms like {{(egg ..)}}, replace {{needs}} or {{depends}} with {{dependencies}}, replace {{test-depends}} to {{test-dependencies}} and add a {{(components (extension ..))}} entry which corresponds to {{standard-extension}} from the old {{.setup}} file. For more complex examples of {{.egg}} files, just look through the [[https://wiki.call-cc.org/chicken-projects/egg-index-5.html|list of available CHICKEN 5 eggs]]. There are a few in there with multiple source files and even some with custom build scripts. === Porting other author's eggs If you want to port old eggs someone else made to a new Chicken version, follow the steps above for the porting itself. Other than that, there are two things you should regard. First, you can find the repositories of Chicken eggs on these lists: * [[https://www.upyum.com/eggs-repo/egg-repositories.4.html|Chicken 4]] * [[https://www.upyum.com/eggs-repo/egg-repositories.5.html|Chicken 5]] Second, be sure to check back with the original author (their email address is usually in the metadata files of the egg) so they're aware of and okay with you porting their code. And finally, to get the egg listed in the index, announce it on the mailing list. === Known changes to existing eggs ==== readline The [[/eggref/4/readline|readline]] egg hasn't been ported to C5. Instead there's the [[/eggref/5/breadline|breadline]] egg which implements a simpler API exposing more of readline's functionality. ==== hyde, clojurian The {{hyde-atom}} and {{clojurian-syntax}} imports have been renamed to {{(hyde atom)}} and {{(clojurian syntax)}}. ==== opengl-glew The [[/eggref/4/opengl-glew|opengl-glew]] egg has not been ported to C5. Instead there's the [[/eggref/5/epoxy|epoxy]] egg which implements a nearly drop-in API.
Description of your changes:
I would like to authenticate
Authentication
Username:
Password:
Spam control
What do you get when you add 16 to 8?