Skip to content

Instantly share code, notes, and snippets.

View zachdaniel's full-sized avatar

Zach Daniel zachdaniel

View GitHub Profile
@zachdaniel
zachdaniel / stream_distribute.ex
Last active May 4, 2024 14:08
A small demo to show how you might, given a stream, do a "fan out", processing different elements in separate streams. Powered by simple primitives like `Stream.resource` and `spawn_link`. Open in Livebook: https://livebook.dev/run?url=https%3A%2F%2Fgist.github.com%2Fzachdaniel%2Fd5ab06a9d2362fceeb6d27c37b206e28
<!-- livebook:{"persist_outputs":true} -->
# Distribute
## Section
A small toy to show how you might, given a stream, do a "fan out", processing different elements in separate streams. Powered by simple primitives like `Stream.resource` and `spawn_link`.
```elixir
defmodule Distribute do

What does "no lock-in" mean in the context of Ash

I think a reasonable definition of "no lock-in" is required. To me its the ability to “start making new choices”, not necessarily “you can push a button and remove your ash stuff”. But we'll get to ejecting at the end.

Ash is stateless. You call functions and it follows the instructions defined in the action. It supports "dropping the bottom" out of any given operation, by overriding whatever action Ash was going to take, And it will happily work along side ecto resources (or w/e) that modify the underlying data it works with.

Keeping in mind that Ash does significantly more than just simple data manipulation/crud, lets look at a simple example.

Comparing usage of Ash & Ecto

# https://gist.github.com/Gazler/b4e92e9ab7527c7e326f19856f8a974a

Application.put_env(:phoenix, :json_library, Jason)

Application.put_env(:sample, SamplePhoenix.Endpoint,
  http: [ip: {127, 0, 0, 1}, port: 5001],
  server: true,
@zachdaniel
zachdaniel / prewalk_with_branch.ex
Created November 14, 2023 02:29
An implementation of `Macro.prewalk/2` with a branch accumulator
defmodule Macro do
@doc """
Copy of `Macro.prewalk/2` w/ a branch accumulator
"""
def prewalk(ast, fun) when is_function(fun, 1) do
elem(prewalk(ast, nil, nil, fn x, nil, nil -> {fun.(x), nil} end), 0)
end
@doc """
Copy of `Macro.prewalk/3` w/ a branch accumulator
@zachdaniel
zachdaniel / libraries_and_frameworks.md
Last active June 29, 2023 16:42
EEF Working Group Proposal: Libraries and Frameworks Working Group

Libraries and Frameworks Working Group

Mission Statement

  • To provide resources for library and framework authors to ensure that BEAM languages have a rich, vibrant ecosystem with a high degree of developer experience. Main Objectives
  • Provide and maintain best practices on library and framework standardization, documentation, code, and distribution. Collaborate to work on and make proposals for underlying tooling that improve the experience for library/framework authors and users.
  • Provide more visibility into the library ecosystem of Elixir on behalf of both authors and users.
  • (if Build and Packaging want to move this here, we could also take this over) Improve the user experience in generating and accessing documentation from the shell, IDEs, web pages, and more.

There are more than a few different ways you could do that. The simplest one would be to modify the actions that are created, by defining them yourself or adding behavior to them.

  1. creating them yourself, if you do this, AshAuthentication will just validate that the action contains the correct elements:
read :sign_in_with_password do 
  ...
  # can also put it in a module: prepare RequireGoogleSignInForFoo
  prepare fn query, result -> 
 if is_foo(Ash.Changeset.get_argument(query, :email)) do 
defmodule Mochi.Deck do
use Ash.Resource,
data_layer: AshJsonApiWrapper.DataLayer
actions do
defaults [:read]
end
json_api_wrapper do
finch Mochi.Finch
@zachdaniel
zachdaniel / sat_solver.gleam
Last active October 19, 2022 19:13
sat_solver.gleam
// This heavily borrows (and is essentialy just a port) of https://andrew.gibiansky.com/blog/verification/writing-a-sat-solver/
import gleam/io
import gleam/list
import gleam/int
import gleam/option.{None, Option, Some}
type Expr {
Var(Int)
And(Expr, Expr)
Or(Expr, Expr)
defmodule BetterComponent do
defmodule Live do
defmacro __using__(opts) do
quote do
import BetterComponent
use Surface.LiveComponent
def update(assigns, socket) do
case assigns[:__event__] do
defmodule BetterComponent do
defmodule Live do
defmacro __using__(opts) do
quote do
import BetterComponent
use Surface.LiveComponent
def update(assigns, socket) do
case assigns[:__event__] do