How to load weather data using LISP

LISP, which stands for List Processing, is a programming language known for its unique approach to data representation and manipulation through linked lists. Originally developed in the late 1950s, LISP has played a crucial role in the development of artificial intelligence and symbolic reasoning systems. One of its distinctive features is its homoiconic nature, where code and data share a common syntax, allowing programs to be easily manipulated as data structures. LISP is well-suited for tasks such as symbolic reasoning, language processing, and rule-based systems, and fits well into various AI methodologies. Its dialects, including Common Lisp and Scheme, are used in a variety of domains, from academic research to specific applications in artificial intelligence, robotics, and computer-aided design. The simplicity of its syntax and its expressive power make LISP a language of choice for those seeking flexibility and abstraction in programming. For these reasons, adding weather data as input to a LISP program often is a valuable addition to many LISP-based projects.

In this article we will show how to load weather data into a LISP program using Visual Crossing’s Timeline API. We will use Common LISP syntax, but the basic code is easily adaptable to virtually any modern LISP environment.

Common LISP doesn’t have built-in support for making HTTP requests or handling JSON responses in its standard library. However, you can easily use external libraries to achieve this functionality. One popular choice for making HTTP requests in Common Lisp is Drakma, and for JSON parsing, you can use a library such as JSON. If your environment is configured to use QuickLISP to manage libraries, you can use an import command such as this one to load these.

(ql:quickload '(:drakma :json)) 

Note that there are various HTTP and JSON libraries that you can use instead of these. If you prefer to use different libraries, simply modify the code below to match the calling conventions of your chosen libraries.

Once we’ve loaded our HTTP and JSON libraries we can use the following LISP code to fetch weather data from the Visual Crossing Timeline API and print a sample result.

Sample Code

(defun get-weather (api-key location start-date end-date)
  (let* ((api-endpoint "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/")
         (params `(("key" . ,api-key)
                   ("location" . ,location)
                   ("startDate" . ,start-date)
                   ("endDate" . ,end-date)))
         (url (format nil "~a?~a" api-endpoint (drakma:encode-query-string params)))
         (response (drakma:http-request url)))
    (when (= (cdr (assoc :status response)) 200)
      (let* ((json-data (json:decode (drakma:body-string (cdr (assoc :content response))))))
        (format t "Weather data:~%")
        (format t "Date: ~a, Temperature: ~a°C, Precipitation: ~a mm~%"
                (getf (aref (getf json-data :days) 0) :datetimeStr)
                (getf (aref (getf json-data :days) 0) :temp2m)
                (getf (aref (getf json-data :days) 0) :precipitation))))))
                
;; Replace these values with your actual API key and location
(setq api-key "YOUR_API_KEY")
(setq location "Leesburg, VA")
(setq start-date "2023-01-01")
(setq end-date "2023-01-07")

(get-weather api-key location start-date end-date)

(Before using this code directly, make sure to replace “YOUR_API_KEY” with your actual Visual Crossing API key.  You can obtain a free API key by signing up for a Visual Crossing Weather account.)

This example fetches the weather forecast for a given period (January 1, 2023 through January 7, 2023) for a specified location (Leesburg, VA).  You can adjust these parameters according to your specific requirements. For more information on how to do that, keep reading.

Understanding the sample

Let’s break this code sample down into sections, to better understand what it is doing in detail.

The first part of the code defines a get-weather function that takes our API Key, the location, a start date, and an end date as parameters. It then configured an HTTP query to the Visual Crossing Timeline API URL that will retrieve the weather data for these parameters. Then it uses the HTTP library to send the URL to Visual Crossing and retrieve the results.

(defun get-weather (api-key location start-date end-date)
  (let* ((api-endpoint "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/")
         (params `(("key" . ,api-key)
                   ("location" . ,location)
                   ("startDate" . ,start-date)
                   ("endDate" . ,end-date)))
         (url (format nil "~a?~a" api-endpoint (drakma:encode-query-string params)))
         (response (drakma:http-request url)))

The next part of the code checks to see if the HTTP response returned a success code (200). If it did, then it uses the JSON library to parse the HTTP response.

    (when (= (cdr (assoc :status response)) 200)
      (let* ((json-data (json:decode (drakma:body-string (cdr (assoc :content response))))))

The final code in our function uses the parsed JSON result to display the temperature and precipitation each day in our weather data result.

        (format t "Weather data:~%")
        (format t "Date: ~a, Temperature: ~a°C, Precipitation: ~a mm~%"
                (getf (aref (getf json-data :days) 0) :datetimeStr)
                (getf (aref (getf json-data :days) 0) :temp2m)
                (getf (aref (getf json-data :days) 0) :precipitation))))))

Although this function is designed to be reusable, you would need to make some changes before using it in production code. For example, you would want to improve the rudimentary error handling. Also, you would likely want to do something more clever than simply printing a few weather measures. Instead, you would likely want to pass them along to some type of analysis or perhaps create a more sophisticated display system.

The last part of the code sample simply sets up the variables for our query, including our API Key, location, and dates. In production code, you could drive parameters such as the location and dates from user input or based on the type of analysis that you are trying to accomplish. The code then calls the get-weather function that we defined above to do the heavy lifting.

;; Replace these values with your actual API key and location
(setq api-key "YOUR_API_KEY")
(setq location "Leesburg, VA")
(setq start-date "2023-01-01")
(setq end-date "2023-01-07")

(get-weather api-key location start-date end-date)

This is just a sample that has been simplified to show the basic flow of querying data and parsing Visual Crossing Weather JSON results in LISP.  Obviously, production code would be more careful in handling error cases and more flexible in the data being queried.  However, this should give any LISP coder a good starting point to use when developing your own LISP weather applications.

Questions or need help?

If you have a question or need help, please post on our actively monitored forum for the fastest replies. You can also contact us via our support site or drop us an email at support@visualcrossing.com.