pushdown.scala

Posted on by Mandla Mbuli

pushdown is a script I wrote during lockdown to keep track of pushups that I was doing. When learning a new language I like to convert existing things because it is easier, I have already thought about the problem I just need to write the solution figuring out the syntax of the new language

Getting started

I already have coursier installed (see my setup setup on how I do that)

Thought about using giter8 template as suggested by devinsideyou, but decided go with what comes default with coursier so I can gain an appreciation of what the templates give me.

I followed this one

Move everything in current pushdown directory into pushdown.py

    sbt new scala/scala3.g8

takes a little longer than I expected the first time I ran it.

    pushdown/pushdown.scala on  master [?] is 📦 v0.1.0 via ☕ v11.0.20 via 🆂 
     ls --tree
    drwxr-xr-x   - mandla  6 Jun 06:00  .
    drwxr-xr-x   - mandla  6 Jun 06:00 ├──  project
    .rw-r--r--  19 mandla  6 Jun 06:00 │  └──  build.properties
    drwxr-xr-x   - mandla  6 Jun 06:00 ├──  src
    drwxr-xr-x   - mandla  6 Jun 06:00 │  ├──  main
    drwxr-xr-x   - mandla  6 Jun 06:00 │  │  └──  scala
    .rw-r--r-- 110 mandla  6 Jun 06:00 │  │     └──  Main.scala
    drwxr-xr-x   - mandla  6 Jun 06:00 │  └──  test
    drwxr-xr-x   - mandla  6 Jun 06:00 │     └──  scala
    .rw-r--r-- 268 mandla  6 Jun 06:00 │        └──  MySuite.scala
    .rw-r--r-- 258 mandla  6 Jun 06:00 ├── 󰨖 build.sbt
    .rw-r--r-- 338 mandla  6 Jun 06:00 └──  README.md

Then run

  sbt

and the first thing I miss from the devinsideyou template is the r for run. I must say, I really like sbt so far. A little more than cargo cause of the interactive shell.

It does it’s thing, I then get this output

[info] running hello 
Hello world!
I was compiled by Scala 3. :)
[success] Total time: 19 s, completed 06 Jun 2024, 06:09:36
sbt:pushdown.scala> 

So far, so good.

Next, I know this is a CLI application, so I want something like click (for python) or clap (for rust). I am happy to let other people handle the CLI stuff for me.

The first thing I do then is to find out what the crate.io kasite for scala is. Searching for scala package search lands me on: scaladex which looks like a portmanteau of scala and index.

A search for cli gives finds me zio/zio-cli I take it because:

  1. I don’t want to compare the “best” cli tool, I just need one that can autogenerate help for me, I can always change it later if it doesn’t suit my needs.
  2. It has ZIO, I am curious about ZIO, I watched 3 videos by devinsideyou about ZIO and… ZIO holds weight that is it good for okay.

Now, let’s add the package and see if the hello world works.

Add the dependency

  val scala3Version = "3.4.2"

  lazy val root = project
    .in(file("."))
    .settings(
      name := "pushdown.scala",
      version := "0.1.0-SNAPSHOT",
      scalaVersion := scala3Version,
      libraryDependencies += "dev.zio" %% "zio-cli" % "0.6.0",
      libraryDependencies += "org.scalameta" %% "munit" % "1.0.0" % Test
    )

Try to run it and :-(

sbt:pushdown.scala> run
[info] Updating pushdown-scala_3
[info] Resolved pushdown-scala_3 dependencies
[warn] 
[warn]  Note: Unresolved dependencies path:
[error] stack trace is suppressed; run last update for the full output
[error] (update) sbt.librarymanagement.ResolveException: Error downloading dev.zio:zio-cli_3:0.6.0
[error]   Not found
[error]   Not found
[error]   not found: /home/leny/.ivy2/localdev.zio/zio-cli_3/0.6.0/ivys/ivy.xml
[error]   not found: https://repo1.maven.org/maven2/dev/zio/zio-cli_3/0.6.0/zio-cli_3-0.6.0.pom
[error] Total time: 2 s, completed 06 Jun 2024, 06:34:12

Which looks like it is search locally for zio-cli then trying maven central. So maybe I should just find a way to specify scaladex as a place to search. Turns out there isn’t a 0.6.0 version. I literally browsed the maven repo and can onl y find 0.5.0. Looking at the scaladex page also only shows upto 0.5.0 so, that must be right.

Restart sbt and try build again and…

[info] started sbt server
sbt:pushdown.scala> run
[info] compiling 1 Scala source to /home/leny/Izinto/Proyectos/code/scripts/pushdown/pushdown.scala/target/scala-3.4.2/classes ...
[info] running Sample 
   _____                       __       _______ __ 
  / ___/____ _____ ___  ____  / /__    / ____(_) /_
  \__ \/ __ `/ __ `__ \/ __ \/ / _ \  / / __/ / __/
 ___/ / /_/ / / / / / / /_/ / /  __/ / /_/ / / /_  
/____/\__,_/_/ /_/ /_/ .___/_/\___/  \____/_/\__/  
                    /_/                            


Sample Git v1.1.0 -- Sample implementation of git clone

USAGE

  $ clone clone [(-l, --local)] <repository>

COMMANDS

  clone [(-l, --local)] <repository>  Creates a copy of an existing repository

[success] Total time: 30 s, completed 06 Jun 2024, 06:55:37
sbt:pushdown.scala> 

It worked and the hello world works. Time to plan

Problems for next time.

It is now next time (June 8, 2024)

Pushdown design

One of the things I like about FP is that I should be to create something similar to kwalk. There is an input, a black box and an output. I haven’t not managed to do this yet, so let’s try again.

features:

  • I want a reminder to do push-ups
  • I want to do push-ups based on my goals
  • Goal are like:
    • 20 push-ups every 60min
    • x push-ups where x increases normally till y then decrease till x repeat all this 5 times
    • basically a Goal is a template of the push-ups I want to do
  • Log how many push-ups I managed to do
    • Allow me to add a comment on how it was if I want
    stateDiagram-v2
    direction LR
        [*] --> Plan
        note left of Plan
          Planning stage either reads the plans for a file or
          gets them from interactive prompts
        end note
        Plan --> Run
        state Run {
            [*] --> countdown
            countdown --> notify
            notify --> savelogs
            savelogs --> if_state <>: "continue?"
            if_state --> countdown: Yes
            if_state --> [*]: No
        }
        Run --> Summarize
        Summarize --> [*]

This was just to play with mermaid.js

The CLI

Let’s understand zio-cli

commit: 921d162

Don’t know how to run the app though. What is a native image I wonder.

How will this thing be run?

ZIO cli has a plugin which is meant to use nativeImage for creating a standalone executable. I can’t get the right version of this plugin though. I tried using nativeImage directly and it has an issue which I’m lazy to figure out. I ended up finding sbt assembly which creates a jar which I have to run with java. Not ideal but meh. Good enough for now.

Let’s add a timer next