this post was submitted on 09 Feb 2025
7 points (76.9% liked)
General Programming Discussion
8724 readers
36 users here now
A general programming discussion community.
Rules:
- Be civil.
- Please start discussions that spark conversation
Other communities
Systems
Functional Programming
Also related
founded 6 years ago
MODERATORS
you are viewing a single comment's thread
view the rest of the comments
view the rest of the comments
I've seen plenty of useful code written by LLMs. In fact, I use DeepSeek R1 all the time now, and I'm shocked at how good it is at writing clean code that generally works out of the box. Just the other day, I threw a json schema at it, and asked it to create a relational table schema to store it in SQL which it did respecting relationships like foreign keys. That would've been a couple of hours of work for me of just typing it all out. Not only that, but it actually explains its reasoning step by step, and a lot of that looks just the same way I would think about solving a problem. Here's a concrete example for you from a recent session.
First, I know that http-kit is a Clojure library for making HTTP requests. So I'll need to include the http-kit dependency in the project.clj or deps.edn file. But the user probably just wants the code, so maybe mention the dependencies they need to add.
Next, downloading the image. Using http-kit's
get
function, which returns a promise. I'll need to handle the response asynchronously. Wait, but maybe they want a synchronous download? The example might use async, but perhaps for simplicity, use the sync version. Alternatively, handle the async with a future or something. Hmm.Once the image is downloaded, the response's body will be the bytes of the image. Then, store that into SQLite. For SQLite, I'll need a Clojure library. The common one is org.clojure/java.jdbc, and the SQLite JDBC driver. So dependencies would be [org.clojure/java.jdbc "0.7.12"] and [org.xerial/sqlite-jdbc "3.36.0.3"], or similar versions.
Then, creating a database connection. The JDBC URL would be something like "jdbc:sqlite:images.db". Then, I need to make sure the table exists. The table should have at least an id, maybe a name or URL, and the image data as a BLOB. So create a table if not exists with columns like id integer primary key, url text, image blob, created_at timestamp.
The function steps would be:
Download the image from the URL using http-kit.
Check if the response is successful (status 200).
Get the byte array from the response body.
Insert the URL and the byte array into the SQLite database.
Possible issues: handling exceptions, like invalid URL, non-200 status, or database errors. Also, binary data in SQLite. Need to make sure the image is stored as a BLOB.
Putting it all together.
Wait, in Clojure, when using jdbc, inserting a byte array can be done by converting it to a byte-array or using .getBytes, but SQLite's BLOB expects a byte array. So in the insert statement, the parameter should be the byte array directly.
So the code outline would be something like:
(ns myapp.core
(:require [org.httpkit.client :as http]
[clojure.java.jdbc :as jdbc]))
(def db-spec {:classname "org.sqlite.JDBC"
:subprotocol "sqlite"
:subname "images.db"})
(defn create-images-table []
(jdbc/db-do-commands db-spec
(jdbc/create-table-ddl :images
[[:id :integer :primary :key :autoincrement]
[:url :text]
[:image :blob]
[:created_at :datetime :default :current_timestamp]])))
(create-images-table) ; Ensure table exists
(defn download-and-save-image [url]
(let [response @(http/get url {:as :byte-array}) ; synchronous GET, response is a map
status (:status response)
body (:body response)]
(if (= 200 status)
(jdbc/insert! db-spec :images {:url url :image body})
(throw (ex-info "Failed to download image" {:url url :status status})))))
Wait, but in the http-kit get request, by default, the body is a string. But for binary data like images, we need to set :as :byte-array to get the body as a byte array. Yes.
Also, the @ is dereferencing the promise, making it synchronous. So the function will block until the download is complete.
But what about error handling? Maybe wrap in a try-catch.
Also, the jdbc/insert! function will handle the byte array correctly if the column is a BLOB. SQLite's JDBC driver should accept a byte array for BLOB.
Testing the code: need to make sure that the dependencies are correctly added. The user should have http-kit, java.jdbc, and sqlite-jdbc in their dependencies.
Potential issues: If the URL doesn't point to an image, or if the response is not 200. Also, large images might cause memory issues, but that's beyond the scope here.
So the final code would involve:
Setting up the dependencies.
Defining the database spec.
Creating the table if it doesn't exist.
The function to download and save.
I should also mention that the user needs to add the required dependencies to their project.clj or deps.edn.
Another thing: The http/get returns a promise, so using @ to deref it makes the call blocking. So the function is synchronous. That's acceptable for the purpose here.
Also, the created_at column has a default of current timestamp, so when inserting, it's not necessary to provide it.
So the code should work as is, but the user needs to make sure the table is created first. Hence the create-images-table function called once.
But maybe the code should check if the table exists and create it if not, perhaps using a migration approach. But for simplicity, just call create-images-table once.
So, putting it all together, the code would look like that. Also, in the answer, I should explain each part and note the dependencies.
output:
Here's a Clojure function that uses HTTP Kit to download an image and stores it in SQLite. You'll need to add the required dependencies and set up the database table first. Step 1: Add dependencies to your
deps.edn
orproject.clj
Step 2: Database setup and image handling function
Explanation:
Dependencies:
Database Setup:
Image Handling:
Usage:
Notes:
To retrieve the image later, you would need to read the BLOB data from the database and convert it back to a byte array for processing or serving.