Planet Scheme

January 18, 2019

Programming Praxis

Extract Number From String

We have another string-handling exercise today:

Given a string containing a number, extract the number from the string. For instance, the strings “-123”, “-123junk”, “junk-123”, “junk-123junk” and “junk-123junk456” should all evaluate to the number -123.

Your task is to write a program to extract a number from a string. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

by programmingpraxis at January 18, 2019 10:00 AM

January 15, 2019

Programming Praxis

Find The Difference

Today’s question comes from a programming student:

You are given two strings s and t that consist only of lower-case letters. String t was created by adding one letter chosen at random to string s, then shuffling the resulting string. Find the letter that was added to t. For instance, the difference between the two strings “abcdef” and “bfxdeac” is the character “x”.

Your task is to write a program to find the random letter that was added to the string. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

by programmingpraxis at January 15, 2019 10:00 AM

January 11, 2019

Programming Praxis

Parallel Assignment

Recently, I was writing a program where I needed parallel assignment; the details of my program don’t matter. Some languages provide parallel assignment natively; for instance, Python:

Python 2.7.13 (default, Mar 13 2017, 20:56:15)
[GCC 5.4.0] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a,b,c = 1,2,3
>>> print a,b,c
1 2 3
>>> a,b,c = b,c,a
>>> print a,b,c
2 3 1

You can do something similar in C (I think — I’m not sufficiently expert in C to be certain this works):

#define SWAP(x, y) { typeof(x) t = x; x = y; y = t }

Your task is to add parallel assignment to your favorite programming language. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

by programmingpraxis at January 11, 2019 10:00 AM

January 08, 2019

Programming Praxis

Perfect Totient Numbers

A perfect number is a number for which the sum of its proper divisors is equal to the number; for instance, 28 is a perfect number because it is the sum of its proper divisors 1 + 2 + 4 + 7 + 14 = 28.

A perfect totient number (A082897) is a number for which the sum of its iterated totients is equal to the number. For instance, 327 is a perfect totient number; its iterated totients are φ(327) = 216, φ(216) = 80, …, and the sum of 216 + 80 + … = 327. I love number theory; it’s totally useless, and endlessly fascinating, as you will see if you follow the links on OEIS.

Your task is to compute the perfect totient numbers less than 10,000. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

by programmingpraxis at January 08, 2019 10:00 AM

January 04, 2019

Programming Praxis

Self-Locating Strings In Pi

[ I worked half-time during December, still suffering fatigue, then during the Christmas break I visited my daughter in Houston; I’m back at work full-time now. Thanks to all for your good wishes. ]

Numberphile has a short episode about self-locating strings in π; for instance, if you ignore the part before the decimal point and number the digits of π starting from zero, the sixth digit of π is 6 and the two digits starting at the 27th digit are 27.

Your task is to write a program that finds self-locating strings in π (A064810). When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

by programmingpraxis at January 04, 2019 10:00 AM

December 21, 2018

GNU Guix

Reproducible Builds Summit, 4th edition

As it has become tradition, a sizeable delegation of Guix developers attended this year's Reproducible Builds Summit in Paris a little over one week ago. In the Mozilla offices around 50 people representing dozens of free software projects (and also Microsoft) got ready to share ideas and work together on reproducibility problems for three days. As the agenda unfolded we would split up into small groups, each focusing on a different issue. This blog post is an attempt to share impressions from some of these group sessions.

Opam

Opam is the OCaml package manager, and a number of sessions were dedicated to addressing reproducibility problems that affect Opam, such as the lack of accounting for common system packages. One of the outcomes of the session is a script to catch common sources of non-determinism, which should improve the quality of OCaml packages in general, including those that are available through Guix.

Some very productive hack session resulted in a new Guix package importer for Opam packages and various fixes for the Opam package in Guix. The Opam website now also includes instructions on how to install Opam with Guix.

“User stories”

The “user stories” session focused on a couple of questions: How can we put reproducible builds into the hands of users? How do they benefit from it? This has been an on-going theme in Reproducible Builds Summits. We shared ideas about this before: users should be able to choose their provider of package binaries, it should be easy for them to (re)build packages locally, and it should be easy for them to challenge servers that publish binaries. Guix satisfies these requirements but could probably go further. These and other ideas were explored. In particular it was interesting to see several distros work on setting up rebuilders that would allow them to have more diversity and thus more confidence in the binaries that they ship.

Distributing packages over IPFS

Developers of IPFS offered a session on package distribution over IPFS. IPFS implements peer-to-peer unencrypted data storage; there are privacy and censorship-resistance issues that it leaves unaddressed, but its efficiency and convenience are appealing for the distribution of package binaries. An IPFS package landed in Guix right in time for the summit, which allowed us to play with it. Together with fellow Nix hackers, we sketched an incremental path towards IPFS integration in Guix and Nix. We hope to be able to deliver a first implementation of that in Guix soon—stay tuned!

Java and other JVM languages

The Java reproducibility working group discussed what was needed to reproduce builds of Java packages. We focused mainly on reproducing builds with Maven and realized that differences in vocabulary affect our goals. For instance, Maven developers don't consider plugins to be dependencies for the build, while in the context of Guix anything contributing to the build is declared as an input. Our interactions with other projects throughout the summit has led to similar revelations and contributed to improved mutual understanding.

In Guix we have packages for two more JVM languages other than Java itself: Groovy and Clojure. Other JVM languages, such as Scala and Kotlin (both dependencies of Gradle), however, come with additional challenges. The Scala compiler, for example, is written in Scala, and although there are other implementations of the compiler, they are also written in Scala. Julien started writing a bootstrap compiler for Scala in Java, which is already able to produce an AST for Scala files and produce JVM bytecode. In cases like this where it is not feasible to retrace historic steps to bootstrap a language, writing a new compiler implementation may surprisingly be the most reasonable thing to do.

Bootstrapping

We were excited to see increased interest in bootstrapping, which may have been sparked by recent major successes in the early Scheme/C bootstrap for GNU+Linux systems. While a few of us successfully hunted down a confusing miscompilation bug, parts of the early C bootstrap were ported to Nix, demonstrating that the bootstrapping work that started in the context of Guix can benefit other GNU+Linux distributions with minor adaptations.

With the addition of Gash as a Bash and GNU coreutils replacement on the horizon, we are looking forward to another dramatic reduction of the "binary seed" used to bootstrap the GNU system --- first via Guix and hopefully for other free software system distributions in the future.

Thanks!

We would like to thank the organizers who helped make the Reproducible Build Summit a productive, enjoyable and friendly workshop: Beatrice and Gunner of Aspiration, Holger, Nicolas, Vagrant, Chris and Mattia.

About GNU Guix

GNU Guix is a transactional package manager for the GNU system. The Guix System Distribution or GuixSD is an advanced distribution of the GNU system that relies on GNU Guix and respects the user's freedom.

In addition to standard package management features, Guix supports transactional upgrades and roll-backs, unprivileged package management, per-user profiles, and garbage collection. Guix uses low-level mechanisms from the Nix package manager, except that packages are defined as native Guile modules, using extensions to the Scheme language. GuixSD offers a declarative approach to operating system configuration management, and is highly customizable and hackable.

GuixSD can be used on an i686, x86_64, ARMv7, and AArch64 machines. It is also possible to use Guix on top of an already installed GNU/Linux system, including on mips64el and aarch64.

by Julien Lepiller, Gábor Boskovits, Ludovic Courtès, Ricardo Wurmus at December 21, 2018 10:30 AM

December 11, 2018

GNU Guix

Bootstrapping Rust

Slowly, systems programming languages are getting better in the sense of giving more guarantees and automating what can be automated without downsides.

Rust is one of the more promising system programming languages. Its central advantage is that it enforces memory safety and thread safety at compile time, without incurring any runtime overhead.

The part that enforces memory safety is called "the borrow checker".

It has been a long-standing tradition to develop a language far enough to be able to write the language's compiler in the same language, and Rust does the same. Rust is nowadays written in Rust.

We've tracked down the earlier Rust versions, which were written in OCaml, and were planning to use these to bootstrap Rust. But in parallel, John Hodge (Mutabah) developed a Rust compiler, called "mrustc", written in C++.

mrustc is now good enough to compile Rust 1.19.0.

Using mrustc, we were able to build Rust entirely from source with a bootstrap chain like this:

rust@1.28.0
    ^
    |
rust@1.27.2
    ^
    |
rust@1.26.2
    ^
    |
rust@1.25.0
    ^
    |
rust@1.24.1
    ^
    |
rust@1.23.0
    ^
    |
rust@1.22.1
    ^
    |
rust@1.21.0
    ^
    |
rust@1.20.0
    ^
    |
rust@1.19.0
    ^
    |
mrustc@0.8.0
    ^
    |
   g++

Limitations

  • mrustc currently does no borrow checking -- so memory safety of our rust@1.19.0 is mostly guaranteed in the sense of "someone else built rust@1.19.0 using another Rust compiler and thus ran the borrow checker already".

  • The bootstrap chain is rather long. There are plans to extend mrustc to support newer Rust, but it turned out to be difficult.

  • Rust takes reproducible builds seriously, but there are some reproducibility problems left in earlier compilers that pop up very sporadically (mostly because of LLVM, and some because of Rust hashtable poisoning). Help wanted, especially from LLVM people!

  • Each target we want to support has to have support in LLVM, AND mrustc needs to have a specification of the alignment and sizes of the base types.

About GNU Guix

GNU Guix is a transactional package manager for the GNU system. The Guix System Distribution or GuixSD is an advanced distribution of the GNU system that relies on GNU Guix and respects the user's freedom.

In addition to standard package management features, Guix supports transactional upgrades and roll-backs, unprivileged package management, per-user profiles, and garbage collection. Guix uses low-level mechanisms from the Nix package manager, except that packages are defined as native Guile modules, using extensions to the Scheme language. GuixSD offers a declarative approach to operating system configuration management, and is highly customizable and hackable.

GuixSD can be used on an i686, x86_64, ARMv7, and AArch64 machines. It is also possible to use Guix on top of an already installed GNU/Linux system, including on mips64el and aarch64.

by Danny Milosavljevic at December 11, 2018 01:36 PM

December 10, 2018

GNU Guix

Back from SeaGL 2018

SeaGL 2018 has concluded. Thank you to everyone in the local Seattle community who came to participate!

As previously announced, Chris Marusich gave a talk introducing GNU Guix to people of all experience levels. Some very Guixy swag was handed out, including printed copies of this handy Guix reference card. The room was packed, the audience asked great questions, and overall it was tons of fun!

If you weren't able to come to SeaGL this year, that's OK! You can watch a video of the talk below. Happy hacking!

Everyday Use of GNU Guix

by Chris Marusich at December 10, 2018 08:00 AM

December 06, 2018

GNU Guix

GNU Guix and GuixSD 0.16.0 released

We are pleased to announce the new release of GNU Guix and GuixSD, version 0.16.0! This release is (hopefully!) the last one before 1.0—we have been closing most key items for 1.0 over the last few months.

The release comes with GuixSD ISO-9660 installation images, a virtual machine image of GuixSD, and with tarballs to install the package manager on top of your GNU/Linux distro, either from source or from binaries. Guix users can update by running guix pull.

It’s been 5 months since the previous release, during which 95 people contributed code and packages. Here are the highlights.

  • The default substitute URL has been changed to https://ci.guix.info. This is backed by a more powerful build farm with terabytes of storage kindly donated by the Bioinformatics platform of the Berlin Institute of Medical Systems Biology (BIMSB) at the Max Delbrück Center (MDC). The build farm front-end runs Cuirass, our continuous integration tool that was partly developed during two GSoC internships.
  • guix pull now lists new and upgraded packages, and it has a --profile option that allows you to keep several Guix revisions in parallel. Related to that, the new guix describe command displays information about the Guix revision you are using.
  • guix pull now supports channels. In a nutshell, you can specify in ~/.config/guix/channels.scm the channels from which guix pull will fetch Guix as well as, optionally, third-party package repositories. Again guix describe displays all the channels in use and guix describe -f channels produces a “pinned channel” specification that can be used as the channels.scm file of guix pull.
  • Using the new inferior mechanism, you can now interact with a different revision of Guix and even compose packages coming from different revisions of Guix!
  • The output of the command-line tools has been noticeably improved: important events are colorized, guix package and guix system no longer display build logs, and guix build colorizes build logs (in a way that is similar to what Emacs-Guix does.)
  • There are new package transformation options: --with-branch and --with-commit allow you to obtain a package variant straight from its Git repository.
  • Guix had reproducible builds and now it has “reproducible source code downloads”: when a package refers to a Git repository that has disappeared (which is unfortunately not uncommon!), the checkout can be fetched from Software Heritage. That makes Guix one of the first distros to be backed by a long-term archive. See this issue for more info.
  • Our Rust packages are now fully bootstrapped from source, starting from mrustc, a Rust compiler written in C++. This is a victory on this instance of “yogurt software”, and Guix is probably the first distro to achieve this. More on that in a future post!
  • On GuixSD, guix system reconfigure will now always load replacements of system services. That way, when you deem appropriate, you can run herd restart SERVICE to start the upgraded service.
  • As usual, 985 packages were added and 1,945 were upgraded, notably the GNU C Library now at version 2.28 (which, incidentally, allowed us to get rid of our Hurd-specific glibc variant, at last!). Today Guix provides 8,715 packages.
  • The manual is now partially translated into German. The French translation is now 90% complete. You can help translate the manual into your native language by joining the Translation Project.

Pffew, quite a long list already! The release announcement lists additional noteworthy changes and bug fixes you may be interested in.

Enjoy!

About GNU Guix

GNU Guix is a transactional package manager for the GNU system. The Guix System Distribution or GuixSD is an advanced distribution of the GNU system that relies on GNU Guix and respects the user's freedom.

In addition to standard package management features, Guix supports transactional upgrades and roll-backs, unprivileged package management, per-user profiles, and garbage collection. Guix uses low-level mechanisms from the Nix package manager, except that packages are defined as native Guile modules, using extensions to the Scheme language. GuixSD offers a declarative approach to operating system configuration management, and is highly customizable and hackable.

GuixSD can be used on an i686, x86_64, ARMv7, and AArch64 machines. It is also possible to use Guix on top of an already installed GNU/Linux system, including on mips64el and aarch64.

by Ludovic Courtès at December 06, 2018 05:00 PM

December 03, 2018

GNU Guix

GNU Guix receives donation from the Handshake project

Just a few days after it turned six, Guix received a great birthday present: the Handshake project, which works on the design and implementation of a decentralized naming protocol compatible with the Domain Name System (DNS), made a large donation to the GNU Project via the Free Software Foundation (FSF). Of this donation, 100,000 USD go to GNU Guix.

Handshake & Guix logos.

This donation will allow the project to guarantee its independence, invest in hardware for its build farm, and develop new features to benefit all our users.

We will be able to grow the performance and reliability of our existing infrastructure. We also envision better support for new and liberating architectures, and more resilient long-term storage of binaries and source code.

It will also allow us to continue our outreach efforts and attract new interns, for example through Outreachy, to further improve and promote the project.

The project funds are held by the FSF and spending is overseen by a committee currently consisting of Ricardo Wurmus, Tobias Geerinckx-Rice, and Ludovic Courtès, all core Guix developers. The FSF is the fiscal sponsor of free software efforts, including Guix, as part of its Working Together for Free Software fund. Other recipients include GNU Octave, the GNU Tool Chain, and Replicant. Congratulations to them as well!

Above all, a big thank you to Handshake for its support of free software and GNU! The least we could do to show our appreciation was to add a package definition for the Handshake resolver daemon, which we just did.

About GNU Guix

GNU Guix is a transactional package manager for the GNU system. The Guix System Distribution or GuixSD is an advanced distribution of the GNU system that relies on GNU Guix and respects the user's freedom.

In addition to standard package management features, Guix supports transactional upgrades and roll-backs, unprivileged package management, per-user profiles, and garbage collection. Guix uses low-level mechanisms from the Nix package manager, except that packages are defined as native Guile modules, using extensions to the Scheme language. GuixSD offers a declarative approach to operating system configuration management, and is highly customizable and hackable.

GuixSD can be used on i686, x86_64, ARMv7, and AArch64 machines. It is also possible to use Guix on top of an already installed GNU/Linux system, including on mips64el and aarch64.

by Ludovic Courtès, Tobias Geerinckx-Rice, Ricardo Wurmus at December 03, 2018 09:00 PM

November 30, 2018

Adrien Ramos

Live coding tricks for CHICKEN Scheme

First of all, I don’t use any fancy tool like SLIME or Geiser as I don’t use a complex editor like emacs or vim, but these tricks can probably apply to them as well.

My solution involves using csi’s REPL itself because it has a few really good features for debugging, which are sadly not readily available outside of it yet.

I run it within Ma, an ACME clone, but it would work the same with emacs’s run-scheme for example. The only feature you need from your editor is a way to send code to the REPL.

Keep your REPL running

The main principle, if your program is a continuously running loop, is to just run it in a different SRFI-18 thread.

I start by writing a (possibly empty) main procedure running the loop and run it in a thread, I also add a bit of code to make the program behave correcly when building a release or running it outside a REPL.

(import srfi-18)

(define (main) (main))

(define game-thread (thread-start! main))

(cond-expand ((or chicken-script compiling) (thread-join! game-thread))
             (else))

I also keep a little expression handy to restart the game thread when it dies:

#;
(when (eqv? 'terminated (thread-state game-thread))
  (set! game-thread (thread-start! main)))

The #; at the beginning is an expression comment, I feel they aren’t that well known, which is a shame since they are so useful!

csi option and toplevel commands

Now that the little boilerplate code is written, you can start running the interpreter. I highly recommend you run it with the -:x command line flag. With it, exceptions from threads are delivered to the primordial thread (where the REPL runs).

You can inspect exceptions with csi’s toplevel commands ,exn, ,c and ,f N (nice tools that almost nobody uses!)

Lets run some erroneous code as an example of these commands:

#;1> (define (erroneous x) (if (< x 0) 0 (/ (erroneous (- x 1)) x)))
#;2> (erroneous 4)

Error: (/) division by zero
0
0

    Call history:

    <eval>    [erroneous] (/ (erroneous (- x 1)) x)
    <eval>    [erroneous] (erroneous (- x 1))
    <eval>    [erroneous] (- x 1)
    <eval>    [erroneous] (< x 0)
    <eval>    [erroneous] (/ (erroneous (- x 1)) x)
    <eval>    [erroneous] (erroneous (- x 1))
    <eval>    [erroneous] (- x 1)
    <eval>    [erroneous] (< x 0)
    <eval>    [erroneous] (/ (erroneous (- x 1)) x)
    <eval>    [erroneous] (erroneous (- x 1))
    <eval>    [erroneous] (- x 1)
    <eval>    [erroneous] (< x 0)
    <eval>    [erroneous] (/ (erroneous (- x 1)) x)
    <eval>    [erroneous] (erroneous (- x 1))
    <eval>    [erroneous] (- x 1)
    <eval>    [erroneous] (< x 0)   <--

Woops, division by zero! If the exception message isn’t clear enough, or that some of its internal components are interesting (such as the return code of an HTTP request) you can pretty print the exception object with ,exn.

Also note that ,exn will return the exception object, which is then available through the REPL history variables (#2 in this example).

#;2> ,exn
condition: (exn arithmetic)
 exn
    message: "division by zero"
    arguments: (0 0)
    call-chain: (#("<eval>" (/ (erroneous (- x 1)) x) #<frameinfo>) #("<eval>" (erroneous (- x 1)) #<framei...
    location: /
 arithmetic

You can then expand the call chain with ,c:

#;3> ,c
 15:[]  <eval>    [erroneous] (/ (erroneous (- x 1)) x)
 14:[]  <eval>    [erroneous] (erroneous (- x 1))
 13:[]  <eval>    [erroneous] (- x 1)
 12:[]  <eval>    [erroneous] (< x 0)
 11:[]  <eval>    [erroneous] (/ (erroneous (- x 1)) x)
 10:[]  <eval>    [erroneous] (erroneous (- x 1))
 9:[]   <eval>    [erroneous] (- x 1)
 8:[]   <eval>    [erroneous] (< x 0)
 7:[]   <eval>    [erroneous] (/ (erroneous (- x 1)) x)
 6:[]   <eval>    [erroneous] (erroneous (- x 1))
 5:[]   <eval>    [erroneous] (- x 1)
 4:[]   <eval>    [erroneous] (< x 0)
 3:[]   <eval>    [erroneous] (/ (erroneous (- x 1)) x)
 2:[]   <eval>    [erroneous] (erroneous (- x 1))
 1:[]   <eval>    [erroneous] (- x 1)
*0:[]   <eval>    [erroneous] (< x 0)
  ---
  x19:    -1

And inspect a specific call point with ,f N, which will show all the local variables for this point (in this case, x = 0):

#;3> ,f 3
 15:[]  <eval>    [erroneous] (/ (erroneous (- x 1)) x)
 14:[]  <eval>    [erroneous] (erroneous (- x 1))
 13:[]  <eval>    [erroneous] (- x 1)
 12:[]  <eval>    [erroneous] (< x 0)
 11:[]  <eval>    [erroneous] (/ (erroneous (- x 1)) x)
 10:[]  <eval>    [erroneous] (erroneous (- x 1))
 9:[]   <eval>    [erroneous] (- x 1)
 8:[]   <eval>    [erroneous] (< x 0)
 7:[]   <eval>    [erroneous] (/ (erroneous (- x 1)) x)
 6:[]   <eval>    [erroneous] (erroneous (- x 1))
 5:[]   <eval>    [erroneous] (- x 1)
 4:[]   <eval>    [erroneous] (< x 0)
*3:[]   <eval>    [erroneous] (/ (erroneous (- x 1)) x)
  ---
  x19:    0
 2:[]   <eval>    [erroneous] (erroneous (- x 1))
 1:[]   <eval>    [erroneous] (- x 1)
 0:[]   <eval>    [erroneous] (< x 0)

Hack your define

The last little trick I use is a hack I wrote to make define mutate existing procedures instead of rebinding their name to a new one. That way, even procedures passed as argument can be modified.

This version of define is available as an egg for CHICKEN 5, you can install it via chicken-install live-define.

I suggest you only use it when running your code in the REPL, and that you don’t rely on its behaviour outside of live-coding purposes as it might break your code when some optimisations are enabled, such as inlining. It might also give very surprising results when used elsewhere than the toplevel.

To use it I just add this line right after all the usual import statements.

(cond-expand (csi (import live-define)) (else))

Here is a dumb example:

(import live-define)
(define (show f)
  (lambda ()
    (print "showing: " (f))))

(define (foo) "hello")

(define s (show foo))
(s) ; --> showing: hello

(define (foo) "goodbye")
(s) ; --> showing: goodbye

by Kooda at November 30, 2018 10:20 AM

November 22, 2018

Programming Praxis

Car Crash Photos

Today is the Thanksgiving holiday in the United States, and I have much to be thankful for this year, being alive and mostly uninjured after a horrible car crash. While I was in the intensive care unit, I lost over a gallon of blood where the steering wheel punched me in the belly. That blood now sits in my belly, forming a huge bruise and causing me to suffer the fatigue and occasional dizzyness of anemia. I am improving slowly, and will return to work half-days starting next week.

The pictures below were provided by my insurance company. As you look at them remember that I walked away from the crash.

CarCrash01

CarCrash01

CarCrash01

CarCrash01

CarCrash01

CarCrash01

CarCrash01

CarCrash01

CarCrash01

CarCrash01

CarCrash01

CarCrash01

CarCrash01

CarCrash01

CarCrash01

by programmingpraxis at November 22, 2018 10:00 AM

November 02, 2018

Greg Hendershott

Thread names

Sometimes people want Racket threads to have useful names — for example to show in logger output. Here is one way to do it.

When you call thread it returns a thread descriptor.

You may also get the thread descriptor of the current thread using current-thread.

The printed representation of a thread descriptor includes the object-name of its thunk procedure.

Often the thunk is an anonymous function. In that case the function object-name is something like /path/to/file.rkt:1:3 — so the thread descriptor prints as #<thread:/path/to/file.rkt:1:3>.

1
(thread (λ () #f)) ;=> #<thread:/tmp/thread.rkt:9:8>

It is more interesting when you name the thunk:

1
2
(define (foo) #f)
(thread foo) ;=> #<thread:foo>

You can also use object-name on the thread descriptor to extract the thunk’s object-name as a symbol:

1
2
(object-name (thread (λ () #f))) ;=> '/tmp/thread.rkt:18:21
(object-name (thread foo))       ;=> 'foo

What if youñ start 10 threads that all use the same thunk procedure? You can use procedure-rename to rename the thunk each time:

1
2
(thread (procedure-rename foo 'bar)) ;=> #<thread:bar>
(thread (procedure-rename foo 'baz)) ;=> #<thread:baz>

The new name can be any symbol — including one generated at runtime:

1
2
3
4
(define (now-sym) 
  (string->symbol (~a (current-inexact-milliseconds))))
(thread (procedure-rename foo (now-sym))) ;=> ex: #<thread:1541116698791.029>
(thread (procedure-rename foo (now-sym))) ;=> ex: #<thread:1541116698791.18>

Of course, you can include in the generated name any interesting identifying information from your problem domain — such as an “ID” or other details about a “job”, “request”, or “message”.

So something like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#lang at-exp racket/base

(require racket/format)

(define-logger thor)

(define (thor)
  (log-thor-debug @~a{hammering job @(object-name (current-thread))}))

(define (job-id) 
  (string->symbol (~a (current-inexact-milliseconds))))

(thread (procedure-rename thor (job-id)))
(thread (procedure-rename thor (job-id)))

Can produce logger output like this:

1
2
[  debug] thor: hammering job 1541119025888.965
[  debug] thor: hammering job 1541119025889.021

In conclusion, it is possible for threads to have unique names in Racket — provided you’re OK giving unique names to the thunks run by the theads.

by Greg Hendershott at November 02, 2018 12:10 AM

October 25, 2018

Programming Praxis

Car Crash

On Saturday morning I had a head-on collision at 75MPH, Medevac helicopter, serious internal bleeding, no broken bones. I spent four days in hospital, including one-and-a-half days in intensive care. I am home now, moving slowly but mostly okay.

I was alone in the car on an interstate highway early in the morning, heading to a weekend with friends away from home. About a minute ahead of me, an 18-wheel tractor/trailer rig hit a deer, lost control, jack-knifed and overturned, leaving the right lane blocked with the bottom of the tractor facing oncoming traffic. Because it was still astronomical twilight, with no moon and no street lamps, I did not see the tractor until it was within range of my headlights, and I was unable to avoid the collision, although I did partially swerve and struck only the right half of my car, from centerline to right side, spinning twice.

In the car about fifteen seconds behind me were four volunteer firefighters on their way to start their shift, so they were on the scene in seconds. They helped me out of the car, and I walked under my own power to the ambulance. The trainee driver of the truck was uninjured. The lead driver of the truck was asleep in the cab’s bed, and suffered a broken left leg.

My left ankle has a deep bruise, but is not broken, from striking the brake pedal; it is painful. My belly has a deep bruise from striking the steering wheel, and was the source of the internal bleeding; I take blood-thinning medication due to two prior pulmonary embolisms, so the bleeding was serious. I was flown from a local hospital to a regional first-class trauma center shortly after the crash. They monitored the bleeding, which stopped on its own after about two days without need for surgery (which was a real possibility). The bruise on my right belly is about twice the size of my right hand with fingers splayed wide, and is mostly black, with a few tinges of deep purple; it is not painful unless I bend or twist badly, which I have learned not to do. I am wearing a corset (the hospital calls it an abdominal binder) and taking a very low dose of pain-killers.

I’ve spoken to my boss; she even came to the hospital to visit and bring flowers. I’ll be away from work for at least several weeks, and away from blogging for just as long. I would appreciate it if my readers keep doing exercises while I am away; just look for any old exercises that strike your fancy.

by programmingpraxis at October 25, 2018 05:23 PM

October 19, 2018

Programming Praxis

Square Digit Chains

Today’s task appears on Project Euler, Rosetta Code, and Sloane’s, so it is well worth a look; we even did a version of this task in a previous exercise. Here is the Project Euler version of the problem:

A number chain is created by continuously added the square of the digits of a number to form a new number until it has been seen before. For example:

44 → 32 → 13 → 10 → 1 → 1

85 → 89 → 145 → 42 → 20 → 4 → 16 → 37 → 58 → 89

Therefore any chain that arrives at 1 or 89 will become stuck in an endless loop. What is most amazing is that EVERY starting number will eventually arrive at 1 or 89.

How many starting numbers below ten million will arrive at 89?

Your task is to write a program to find the count of starting numbers below ten million that arrive at 89, following the usual Project Euler rule that your computation may take no more than a minute of computation on a recent-vintage personal computer. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

by programmingpraxis at October 19, 2018 09:00 AM