Skip to content

Instantly share code, notes, and snippets.

View Adzz's full-sized avatar

Adam Lancaster Adzz

View GitHub Profile
@Adzz
Adzz / elexer.ex
Last active November 4, 2022 13:20
A lisp lexer / parser for a pairing exercise, written in Elixir. I chose to make this event based for some reason.
# A simple Lisp parser. You could copy paste this into iex (the elixir repl)
# or use a livebook, and you can run the parser like this:
#
# Elexer.parse("(+ 1 -2)")
# A more fully featured prject can be found here: https://github.com/Adzz/elexer
defmodule Elexer do
@moduledoc """
A simple lisp parser.
@Adzz
Adzz / bad_behaviours.ex
Created November 15, 2021 15:45
This is a gist that demos what behaviours and protocols look like in Elixir. Used as part of onboarding
defmodule Shape do
@callback area(map()) :: integer()
@callback perimeter(map()) :: integer()
end
defmodule Square do
defstruct [:side]
@behaviour Shape
@Adzz
Adzz / koppel_to_do.ex
Last active September 15, 2019 12:18
Your task is to design the data layer for a to-do list app. Create the core data structures that track state, along with an API that can be connected to any frontend
# Third round of feature requests
# Extend your design to support one of the following two features:
# Ability to look up, for all users, how many have a todo item with the same name as one of yours.
# Also, explain how to extend your user interface to display the total number of todo items in the
# list currently being viewed. This feature is simple, but there are some easy ways to get it wrong.
# Ability to go back into the past, and see what a user's todo list looked like at any point in time.
# Explain how this would work for todo lists that already exist.
# =================================================================================================
// As you might expect
func add(x int, y int) int {
return x + y
}
// Go functions can return multiple values though, so you
// Can type each of the return values
func swap(x, y string) (string, string) {
return y, x
}
map_1 = %{first: 1, second: 2}
map_2 = %{first: 3, second: 4}
# These just work! 🤩
Zip.apply(map_1, map_2, Add) #=> %{first: 4, second: 6}
Zip.apply(map_1, map_2, Subtract) #=> %{first: 4, second: 6}
defimpl Zip, for: Map do
def apply(a, b, operation) do
# We take the all the keys from b that are also in a
intersection = Map.take(b, Map.keys(a))
Enum.reduce(a, %{}, fn {key, value}, acc ->
Map.put(acc, key, operation.calculate(value, Map.fetch!(intersection, key)))
end)
end
end
defprotocol Subtract do
def calculate(a, b)
end
# And implement it
defimpl Subtract, for: Integer do
def calculate(a, b) when is_integer(b), do: a - b
end
defimpl Subtract, for: Decimal do
defimpl Add, for: Decimal do
def calculate(decimal, decimal_2 = %Decimal{}), do: Decimal.add(decimal, decimal_2)
end
list_1 = [Decimal.new(1), Decimal.new(2)]
list_2 = [Decimal.new(3), Decimal.new(4)]
Zip.apply(list_1, list_2, Add) #=> [Decimal.new(4), Decimal.new(6)]
defimpl Zip, for: List do
def apply(a, b, operation) do
Enum.zip(a, b)
|> Enum.map(fn {a, b} -> operation.calculate(a, b) end)
end
end
# Now we can call it like this:
Zip.apply([1, 2], [3, 4], Add) #=> [4, 6]
defprotocol Add do
def calculate(a, b)
end
# Now we can define implementations of it for the various kinds of
# data types we might get inside our collections that we are zipping.
defimpl Add, for: Integer do
def calculate(a, b) when is_integer(b), do: a + b
end