Tuesday, 30 June 2020

(practical-python->racket approach)

Superficially, it seemed logical to start at the beginning. But upon reading the first few pages, it soon became clear to me that attempting to "translate" them requires a deeper knowledge of Racket than I have today. I thought it best to start with some easier material. So, I started with the introductory material about numbers, strings and lists that was easier to translate. I'll come back to the start later.

Each section of the course includes examples and exercises. My approach is to write a single Racket script which includes all the examples. (Is it even correct to refer to a short Racket program as a script?). I write a separate Racket program for each of the exercises. I'll write any notes I might have in this blog. I'll store the Racket programs in GitHub.

After a few false starts I managed to work out how to get the Racket that I've written to run in both Dr Racket and the Racket repl. I had written a few short Racket functions to reduce the amount of typing to complete the example scripts.

For example, instead of writing (displayln "Python: a = True") I can write (python "a = True"). It's basic text substitution. 

The function that I use to "expand" (racket value) is a little more sophisticated / complicated depending on you point of view.

(define-namespace-anchor anchor)
(define ns (namespace-anchor->namespace anchor))
(define (racket rkt)
  (cond
    [(list? rkt) (display "Racket: ")
                 (writeln rkt)
                 (eval rkt ns)]
    [(string? rkt) (displayln (string-append "Racket: " rkt))]
    [else          (displayln "Racket: Oops")])) 

The racket function will display its arguments and also evaluate the argument if it is a list. 

What took the time to figure this out was that you don't need to provide the namespace to the eval function when you run code in the repl unless you  specify #lang racket. It seems that Dr Racket insist on you specifying a language. So the code wouldn't run in Dr Racket.

I couldn't see a quick solution staring at me from the pages of the documentation. As I was really just performing text substitution, I thought I'd be better off writing a macro.

It took me number of attempts but I did eventually manage to get a macro to do pretty much the same thing. The issue that I came across was that I couldn't work out how to just expand the code with the macro and not evaluate it. So when I ran the script, all the macros were run before the rest of the code and the output was not in the order I wanted. (I guess I could have translated all my "expander" function to macros but I'll leave that for another time).

I went back to the docs and found that what I need to get my racket function working was to create and provide it a namespace. I first used make-base-namespace to create the namespace. I later found that I needed more modules than provided in racket/base to emulate the Python examples. Section 15.1 eval in The Racket Guide had a simple example of creating a namespace based on the "language" being used.

On to the first translation 1.3 Numbers.



Friday, 26 June 2020

(practical-python->racket introduction)

Recently, renowned Python expert David Beazley generously open-sourced his Practical Python Programming course. My Python skills are steadily improving through consistent use and watching talks and tutorials on YouTube. I've learnt a lot from David's talks and tutorials.

Sometimes I feel that my understanding of languages can be more theoretical than practical. I spent too much time learning and not enough time applying my knowledge. Practical Python Programming sounded exactly what I needed. I set out dutifully entering the examples into Python and doing the exercises. It was helpful. I even learnt that the Chicago Transit Authority #22 bus doesn't run at night.

What is Practical Programming though? Well to me, it's writing programs, short or long, to get things done quickly and efficiently. Effectively, it's turning a computer into a personal productivity tool. My current practical programming project helps me analyse companies. It is putting knowledge to use. 

I was mid-way through Chapter 1 of Practical Python Programming when a sudden thought broke my concentration. "This is just the type of material that would help me move forward with Racket. Hmmm, perhaps I should try coding the examples and exercises in Racket?"

So I tried out the introduction to Lists. I found I was able to "translate" the examples to Racket with some difficulty and quite a bit of "Doc Diving". During the process I expanded my knowledge of Racket and reinforced what I already knew. It seemed like a good idea to continue and get as far through the course as I could. I'll try to write about my experience in doing so in this blog as it helps me to remember what I've learnt.

I contacted David Beazley and he was happy for me to blog about my efforts to "translate" his Python to Racket. Though this is not in anyway his endorsement of the contents.

Another word of warning, this is very much a pseudo-mechanical translation. It's turning idiomatic Python into Racket. The code will certainly not be idiomatic Racket code. It could well turn out to be idiotic Racket code. Let's see.

You can read about my approach or go straight to the first section.




Monday, 22 June 2020

Learning Racket

I decided to try to learn Racket. Why?

It's not directly relevant to my current programming in JavaScript, Lua, Python and Rebol. Most of my programming work has been, is, and probably will be, run of the mill application software development. Since I started working as a programmer, languages such as Lisp, Forth and Prolog have always held an element of intrigue for me. They are different from the languages that I use.

Rebol is said to have both Lisp and Forth in its genes. But somehow, it doesn't hold the same level of intrigue. Perhaps its because the majority of people in the Rebol community were intent on using Rebol rather than discussing its design and implementation. The focus was far more on what you could do with Rebol than what you could do to Rebol. It could also be that, to quote a friend, "I wrote Rebol code the same way I wrote COBOL".  On the other hand, it could be that I have reached a reasonable level of fluency and the intrigue has faded during the process.

I didn't start out to learn Racket because I found it intriguing though. I had something else in mind. Functional programming is a hot topic these days (at least in the circles I'm connected with). It is the "only" answer to make use of the ever increasing number of cores in CPUs according to many of its proponents. Object oriented programming is frowned upon in the same circles these days. I use functions in my programs. I use objects in my programs. 

However, I feel that I have a superficial understanding of functional programming. I've taken a quick look at Erlang, studied books on functional programming in JavaScript and watched YouTube videos promoting functional programming in Python. I have an equally superficial understanding of object-oriented programming. I've half-heartedly studied Java in the past. I have learned a little Ruby and dipped in to the world of "proper" object-oriented programming. 

I believe that I would be a better programmer if I was more fluent in both functional programming and object-oriented programming metaphors. I decided to try to learn a functional style programming language and, after that, to properly try object-oriented programming. 

I've even identified two simple projects that I could use as learning vehicles. I know from experience, that I will only reach the level of fluency in a style of programming when I can use it productively by writing useful code in it.

It was easy for me to choose to use Ruby as a medium for object-oriented programming. The choice was not so easy when it came to functional programming.

I was encouraged to learn Elixir. It seems to have taken over some of people's previous enthusiasm for Ruby. People mentioned "SICP" in glowing terms insinuating that it is the seminal functional programming text. You can follow SICP using Racket. In the past, I had heard favourably of Racket. I took a look. It is very professional presented with a lot of documentation. It is easy to install and get started. 

I decided to work through "How To Design Programs" or HTDP as it appears to be snappily known. I chose the word work carefully. I completed around 40 percent of HTDP and did about 90 percent of the 240 exercises I have so far encountred  I probably spent an hour a day studying HTDP. Sometimes it felt a little like "Wax on, wax off" as the exercises felt a little repetitious to me.

It was taking too long to hold my attention, so I switched to The Racket Guide. I made faster progress but also soon realised that I'll need to complete reading most of the guide before I can start writing Racket programs.

At the moment, I still feel that I have a way to go before I can start on even a small project in Racket to start building some actual fluency. I'm not sure that I have the stamina to finish The Racket Guide as an academic exercise.

Thankfully, I have stumbled across another approach which has boosted my enthusiasm which you can read about at (practical-python->racket introduction).